mirror of https://github.com/tbklang/tlang.git
102 lines
3.3 KiB
D
102 lines
3.3 KiB
D
module compiler.typecheck.exceptions;
|
|
|
|
import compiler.typecheck.core;
|
|
import compiler.symbols.data;
|
|
import compiler.typecheck.resolution;
|
|
import std.string : cmp;
|
|
import std.conv : to;
|
|
import misc.exceptions: TError;
|
|
import compiler.symbols.typing.core;
|
|
|
|
public class TypeCheckerException : TError
|
|
{
|
|
private TypeChecker typeChecker;
|
|
|
|
// NOTE: See if we use, as we seem to overwrite the `msg` value
|
|
// ... in sub-classes of this
|
|
public enum TypeheckError
|
|
{
|
|
GENERAL_ERROR
|
|
}
|
|
|
|
this(TypeChecker typeChecker, TypeheckError errType, string msg = "")
|
|
{
|
|
/* We set it after each child class calls this constructor (which sets it to empty) */
|
|
super("TypeCheck Error ("~to!(string)(errType)~")"~(msg.length > 0 ? ": "~msg : ""));
|
|
this.typeChecker = typeChecker;
|
|
}
|
|
|
|
// TODO: Remove this constructor and make anything that is currently using it
|
|
// ... switch to atleast specifying the errType
|
|
this(TypeChecker typeChecker)
|
|
{
|
|
this(typeChecker, TypeheckError.GENERAL_ERROR);
|
|
}
|
|
}
|
|
|
|
public final class TypeMismatchException : TypeCheckerException
|
|
{
|
|
this(TypeChecker typeChecker, Type originalType, Type attemptedType, string msgIn = "")
|
|
{
|
|
super(typeChecker);
|
|
|
|
msg = "Type mismatch between type "~originalType.getName()~" and "~attemptedType.getName();
|
|
|
|
msg ~= msgIn.length > 0 ? ": "~msgIn : "";
|
|
}
|
|
}
|
|
|
|
public final class CollidingNameException : TypeCheckerException
|
|
{
|
|
/**
|
|
* The previously declared Entity
|
|
*/
|
|
public Entity defined;
|
|
|
|
/**
|
|
* The colliding Entity
|
|
*/
|
|
public Entity attempted;
|
|
|
|
/**
|
|
* The Container we are in
|
|
*/
|
|
private Container c;
|
|
|
|
this(TypeChecker typeChecker, Entity defined, Entity attempted, Container c)
|
|
{
|
|
super(typeChecker);
|
|
|
|
this.defined = defined;
|
|
this.attempted = attempted;
|
|
this.c = c;
|
|
|
|
/* If colliding with the container */
|
|
if(isCollidingWithContainer())
|
|
{
|
|
string containerPath = typeChecker.getResolver().generateName(typeChecker.getModule(), defined);
|
|
string entityPath = typeChecker.getResolver().generateName(typeChecker.getModule(), attempted);
|
|
msg = "Cannot have entity \""~entityPath~"\" with same name as container \""~containerPath~"\"";
|
|
}
|
|
/* If colliding with root (Module) */
|
|
else if(cmp(typeChecker.getModule().getName(), attempted.getName()) == 0)
|
|
{
|
|
string entityPath = typeChecker.getResolver().generateName(typeChecker.getModule(), attempted);
|
|
msg = "Cannot have entity \""~entityPath~"\" with same name as module \""~typeChecker.getModule().getName()~"\"";
|
|
}
|
|
/* If colliding with a member within the container */
|
|
else
|
|
{
|
|
string preExistingEntity = typeChecker.getResolver().generateName(typeChecker.getModule(), typeChecker.findPrecedence(c, attempted.getName()));
|
|
string entityPath = typeChecker.getResolver().generateName(typeChecker.getModule(), attempted);
|
|
msg = "Cannot have entity \""~entityPath~"\" with same name as entity \""~preExistingEntity~"\" within same container";
|
|
}
|
|
}
|
|
|
|
public bool isCollidingWithContainer()
|
|
{
|
|
return attempted.parentOf() == defined;
|
|
}
|
|
|
|
|
|
} |