Compare commits

..

2 Commits

Author SHA1 Message Date
nub31
d771396bd4 Remove unused BasicError 2026-02-25 20:04:21 +01:00
nub31
7b1e202424 ... 2026-02-25 19:39:31 +01:00
2 changed files with 50 additions and 40 deletions

View File

@@ -81,7 +81,7 @@ public class Parser
foreach (var modifier in modifiers) foreach (var modifier in modifiers)
// todo(nub31): Add to diagnostics instead of throwing // todo(nub31): Add to diagnostics instead of throwing
throw new CompileException(Diagnostic.Error("Invalid modifier for function").At(fileName, modifier.Value).Build()); throw BasicError("Invalid modifier for function", modifier.Value);
var name = ExpectIdent(); var name = ExpectIdent();
var parameters = new List<NodeDefinitionFunc.Param>(); var parameters = new List<NodeDefinitionFunc.Param>();
@@ -111,7 +111,7 @@ public class Parser
foreach (var modifier in modifiers) foreach (var modifier in modifiers)
// todo(nub31): Add to diagnostics instead of throwing // todo(nub31): Add to diagnostics instead of throwing
throw new CompileException(Diagnostic.Error("Invalid modifier for struct").At(fileName, modifier.Value).Build()); throw BasicError("Invalid modifier for struct", modifier.Value);
var name = ExpectIdent(); var name = ExpectIdent();
var fields = new List<NodeDefinitionStruct.Field>(); var fields = new List<NodeDefinitionStruct.Field>();
@@ -135,7 +135,7 @@ public class Parser
foreach (var modifier in modifiers) foreach (var modifier in modifiers)
// todo(nub31): Add to diagnostics instead of throwing // todo(nub31): Add to diagnostics instead of throwing
throw new CompileException(Diagnostic.Error("Invalid modifier for struct").At(fileName, modifier.Value).Build()); throw BasicError("Invalid modifier for struct", modifier.Value);
var name = ExpectIdent(); var name = ExpectIdent();
var variants = new List<NodeDefinitionEnum.Variant>(); var variants = new List<NodeDefinitionEnum.Variant>();
@@ -174,7 +174,7 @@ public class Parser
foreach (var modifier in modifiers) foreach (var modifier in modifiers)
// todo(nub31): Add to diagnostics instead of throwing // todo(nub31): Add to diagnostics instead of throwing
throw new CompileException(Diagnostic.Error("Invalid modifier for global variable").At(fileName, modifier.Value).Build()); throw BasicError("Invalid modifier for global variable", modifier.Value);
var name = ExpectIdent(); var name = ExpectIdent();
ExpectSymbol(Symbol.Colon); ExpectSymbol(Symbol.Colon);
@@ -183,7 +183,7 @@ public class Parser
return new NodeDefinitionGlobalVariable(TokensFrom(startIndex), exported, name, type); return new NodeDefinitionGlobalVariable(TokensFrom(startIndex), exported, name, type);
} }
throw new CompileException(Diagnostic.Error("Not a valid definition").At(fileName, Peek()).Build()); throw BasicError("Not a valid definition", Peek());
} }
private NodeStatement ParseStatement() private NodeStatement ParseStatement()
@@ -403,7 +403,7 @@ public class Parser
} }
else else
{ {
throw new CompileException(Diagnostic.Error("Expected start of expression").At(fileName, Peek()).Build()); throw BasicError("Expected start of expression", Peek());
} }
while (true) while (true)
@@ -495,7 +495,7 @@ public class Parser
} }
} }
throw new CompileException(Diagnostic.Error("Expected type").At(fileName, Peek()).Build()); throw BasicError("Expected type", Peek());
} }
private List<Token> TokensFrom(int startIndex) private List<Token> TokensFrom(int startIndex)
@@ -511,7 +511,7 @@ public class Parser
return; return;
} }
throw new CompileException(Diagnostic.Error($"Expected '{keyword.AsString()}'").At(fileName, Peek()).Build()); throw BasicError($"Expected '{keyword.AsString()}'", Peek());
} }
private bool TryExpectKeyword(Keyword keyword) private bool TryExpectKeyword(Keyword keyword)
@@ -533,7 +533,7 @@ public class Parser
return; return;
} }
throw new CompileException(Diagnostic.Error($"Expected '{symbol.AsString()}'").At(fileName, Peek()).Build()); throw BasicError($"Expected '{symbol.AsString()}'", Peek());
} }
private bool TryExpectSymbol(Symbol symbol) private bool TryExpectSymbol(Symbol symbol)
@@ -555,7 +555,7 @@ public class Parser
return token; return token;
} }
throw new CompileException(Diagnostic.Error("Expected identifier").At(fileName, Peek()).Build()); throw BasicError("Expected identifier", Peek());
} }
private bool TryExpectIdent([NotNullWhen(true)] out TokenIdent? ident) private bool TryExpectIdent([NotNullWhen(true)] out TokenIdent? ident)
@@ -613,7 +613,7 @@ public class Parser
private void Next() private void Next()
{ {
if (index >= tokens.Count) if (index >= tokens.Count)
throw new CompileException(Diagnostic.Error("Unexpected end of tokens").At(fileName, Peek()).Build()); throw BasicError("Unexpected end of tokens", Peek());
index += 1; index += 1;
} }
@@ -686,6 +686,11 @@ public class Parser
return false; return false;
} }
} }
private CompileException BasicError(string message, Token? ident)
{
return new CompileException(Diagnostic.Error(message).At(fileName, ident).Build());
}
} }
public class Ast(string fileName, TokenIdent moduleName, List<NodeDefinition> definitions) public class Ast(string fileName, TokenIdent moduleName, List<NodeDefinition> definitions)

View File

@@ -112,7 +112,7 @@ public class TypeChecker
private TypedNodeStatementFuncCall CheckStatementExpression(NodeStatementExpression statement) private TypedNodeStatementFuncCall CheckStatementExpression(NodeStatementExpression statement)
{ {
if (statement.Expression is not NodeExpressionFuncCall funcCall) if (statement.Expression is not NodeExpressionFuncCall funcCall)
throw new CompileException(Diagnostic.Error("Expected statement or function call").At(fileName, statement).Build()); throw BasicError("Expected statement or function call", statement);
return new TypedNodeStatementFuncCall(statement.Tokens, CheckExpression(funcCall.Target), funcCall.Parameters.Select(CheckExpression).ToList()); return new TypedNodeStatementFuncCall(statement.Tokens, CheckExpression(funcCall.Target), funcCall.Parameters.Select(CheckExpression).ToList());
} }
@@ -133,7 +133,7 @@ public class TypeChecker
var value = CheckExpression(statement.Value); var value = CheckExpression(statement.Value);
if (!value.Type.IsAssignableTo(type)) if (!value.Type.IsAssignableTo(type))
throw new CompileException(Diagnostic.Error("Type of variable does match type of assigned value").At(fileName, value).Build()); throw BasicError("Type of variable does match type of assigned value", value);
scope.DeclareIdentifier(statement.Name.Ident, type); scope.DeclareIdentifier(statement.Name.Ident, type);
@@ -198,10 +198,10 @@ public class TypeChecker
case NodeExpressionBinary.Op.Modulo: case NodeExpressionBinary.Op.Modulo:
{ {
if (left.Type is not NubTypeSInt and not NubTypeUInt) if (left.Type is not NubTypeSInt and not NubTypeUInt)
throw new CompileException(Diagnostic.Error($"Unsupported type for left hand side arithmetic operation: {left.Type}").At(fileName, left).Build()); throw BasicError($"Unsupported type for left hand side arithmetic operation: {left.Type}", left);
if (right.Type is not NubTypeSInt and not NubTypeUInt) if (right.Type is not NubTypeSInt and not NubTypeUInt)
throw new CompileException(Diagnostic.Error($"Unsupported type for right hand side arithmetic operation: {right.Type}").At(fileName, right).Build()); throw BasicError($"Unsupported type for right hand side arithmetic operation: {right.Type}", right);
type = left.Type; type = left.Type;
break; break;
@@ -210,10 +210,10 @@ public class TypeChecker
case NodeExpressionBinary.Op.RightShift: case NodeExpressionBinary.Op.RightShift:
{ {
if (left.Type is not NubTypeUInt) if (left.Type is not NubTypeUInt)
throw new CompileException(Diagnostic.Error($"Unsupported type for left hand side of left/right shift operation: {left.Type}").At(fileName, left).Build()); throw BasicError($"Unsupported type for left hand side of left/right shift operation: {left.Type}", left);
if (right.Type is not NubTypeUInt) if (right.Type is not NubTypeUInt)
throw new CompileException(Diagnostic.Error($"Unsupported type for right hand side of left/right shift operation: {right.Type}").At(fileName, right).Build()); throw BasicError($"Unsupported type for right hand side of left/right shift operation: {right.Type}", right);
type = left.Type; type = left.Type;
break; break;
@@ -226,10 +226,10 @@ public class TypeChecker
case NodeExpressionBinary.Op.GreaterThanOrEqual: case NodeExpressionBinary.Op.GreaterThanOrEqual:
{ {
if (left.Type is not NubTypeSInt and not NubTypeUInt) if (left.Type is not NubTypeSInt and not NubTypeUInt)
throw new CompileException(Diagnostic.Error($"Unsupported type for left hand side of comparison: {left.Type}").At(fileName, left).Build()); throw BasicError($"Unsupported type for left hand side of comparison: {left.Type}", left);
if (right.Type is not NubTypeSInt and not NubTypeUInt) if (right.Type is not NubTypeSInt and not NubTypeUInt)
throw new CompileException(Diagnostic.Error($"Unsupported type for right hand side of comparison: {right.Type}").At(fileName, right).Build()); throw BasicError($"Unsupported type for right hand side of comparison: {right.Type}", right);
type = NubTypeBool.Instance; type = NubTypeBool.Instance;
break; break;
@@ -238,10 +238,10 @@ public class TypeChecker
case NodeExpressionBinary.Op.LogicalOr: case NodeExpressionBinary.Op.LogicalOr:
{ {
if (left.Type is not NubTypeBool) if (left.Type is not NubTypeBool)
throw new CompileException(Diagnostic.Error($"Unsupported type for left hand side of logical operation: {left.Type}").At(fileName, left).Build()); throw BasicError($"Unsupported type for left hand side of logical operation: {left.Type}", left);
if (right.Type is not NubTypeBool) if (right.Type is not NubTypeBool)
throw new CompileException(Diagnostic.Error($"Unsupported type for right hand side of logical operation: {right.Type}").At(fileName, right).Build()); throw BasicError($"Unsupported type for right hand side of logical operation: {right.Type}", right);
type = NubTypeBool.Instance; type = NubTypeBool.Instance;
break; break;
@@ -286,7 +286,7 @@ public class TypeChecker
case NodeExpressionUnary.Op.Negate: case NodeExpressionUnary.Op.Negate:
{ {
if (target.Type is not NubTypeSInt and not NubTypeUInt) if (target.Type is not NubTypeSInt and not NubTypeUInt)
throw new CompileException(Diagnostic.Error($"Unsupported type for negation: {target.Type}").At(fileName, target).Build()); throw BasicError($"Unsupported type for negation: {target.Type}", target);
type = target.Type; type = target.Type;
break; break;
@@ -294,7 +294,7 @@ public class TypeChecker
case NodeExpressionUnary.Op.Invert: case NodeExpressionUnary.Op.Invert:
{ {
if (target.Type is not NubTypeBool) if (target.Type is not NubTypeBool)
throw new CompileException(Diagnostic.Error($"Unsupported type for inversion: {target.Type}").At(fileName, target).Build()); throw BasicError($"Unsupported type for inversion: {target.Type}", target);
type = NubTypeBool.Instance; type = NubTypeBool.Instance;
break; break;
@@ -325,7 +325,7 @@ public class TypeChecker
{ {
var type = scope.GetIdentifierType(expression.Value.Ident); var type = scope.GetIdentifierType(expression.Value.Ident);
if (type is null) if (type is null)
throw new CompileException(Diagnostic.Error($"Identifier '{expression.Value.Ident}' is not declared").At(fileName, expression.Value).Build()); throw BasicError($"Identifier '{expression.Value.Ident}' is not declared", expression.Value);
return new TypedNodeExpressionLocalIdent(expression.Tokens, type, expression.Value); return new TypedNodeExpressionLocalIdent(expression.Tokens, type, expression.Value);
} }
@@ -351,43 +351,43 @@ public class TypeChecker
case NubTypeStruct structType: case NubTypeStruct structType:
{ {
if (!moduleGraph.TryResolveModule(structType.Module, out var module)) if (!moduleGraph.TryResolveModule(structType.Module, out var module))
throw new CompileException(Diagnostic.Error($"Module '{structType.Module}' not found").At(fileName, expression.Target).Build()); throw BasicError($"Module '{structType.Module}' not found", expression.Target);
if (!module.TryResolveType(structType.Name, currentModule == structType.Module, out var typeDef)) if (!module.TryResolveType(structType.Name, currentModule == structType.Module, out var typeDef))
throw new CompileException(Diagnostic.Error($"Type '{structType.Name}' not found in module '{structType.Module}'").At(fileName, expression.Target).Build()); throw BasicError($"Type '{structType.Name}' not found in module '{structType.Module}'", expression.Target);
if (typeDef is not Module.TypeInfoStruct structDef) if (typeDef is not Module.TypeInfoStruct structDef)
throw new CompileException(Diagnostic.Error($"Type '{target.Type}' is not a struct").At(fileName, expression.Target).Build()); throw BasicError($"Type '{target.Type}' is not a struct", expression.Target);
var field = structDef.Fields.FirstOrDefault(x => x.Name == expression.Name.Ident); var field = structDef.Fields.FirstOrDefault(x => x.Name == expression.Name.Ident);
if (field == null) if (field == null)
throw new CompileException(Diagnostic.Error($"Struct '{target.Type}' does not have a field matching the name '{expression.Name.Ident}'").At(fileName, target).Build()); throw BasicError($"Struct '{target.Type}' does not have a field matching the name '{expression.Name.Ident}'", target);
return new TypedNodeExpressionMemberAccess(expression.Tokens, field.Type, target, expression.Name); return new TypedNodeExpressionMemberAccess(expression.Tokens, field.Type, target, expression.Name);
} }
case NubTypeEnumVariant enumVariantType: case NubTypeEnumVariant enumVariantType:
{ {
if (!moduleGraph.TryResolveModule(enumVariantType.EnumType.Module, out var module)) if (!moduleGraph.TryResolveModule(enumVariantType.EnumType.Module, out var module))
throw new CompileException(Diagnostic.Error($"Module '{enumVariantType.EnumType.Module}' not found").At(fileName, expression.Target).Build()); throw BasicError($"Module '{enumVariantType.EnumType.Module}' not found", expression.Target);
if (!module.TryResolveType(enumVariantType.EnumType.Name, currentModule == enumVariantType.EnumType.Module, out var typeDef)) if (!module.TryResolveType(enumVariantType.EnumType.Name, currentModule == enumVariantType.EnumType.Module, out var typeDef))
throw new CompileException(Diagnostic.Error($"Type '{enumVariantType.EnumType.Name}' not found in module '{enumVariantType.EnumType.Module}'").At(fileName, expression.Target).Build()); throw BasicError($"Type '{enumVariantType.EnumType.Name}' not found in module '{enumVariantType.EnumType.Module}'", expression.Target);
if (typeDef is not Module.TypeInfoEnum enumDef) if (typeDef is not Module.TypeInfoEnum enumDef)
throw new CompileException(Diagnostic.Error($"Type '{enumVariantType.EnumType.Module}::{enumVariantType.EnumType.Name}' is not an enum").At(fileName, expression.Target).Build()); throw BasicError($"Type '{enumVariantType.EnumType.Module}::{enumVariantType.EnumType.Name}' is not an enum", expression.Target);
var variant = enumDef.Variants.FirstOrDefault(x => x.Name == enumVariantType.Variant); var variant = enumDef.Variants.FirstOrDefault(x => x.Name == enumVariantType.Variant);
if (variant == null) if (variant == null)
throw new CompileException(Diagnostic.Error($"Type '{target.Type}' does not have a variant named '{enumVariantType.Variant}'").At(fileName, expression.Target).Build()); throw BasicError($"Type '{target.Type}' does not have a variant named '{enumVariantType.Variant}'", expression.Target);
var field = variant.Fields.FirstOrDefault(x => x.Name == expression.Name.Ident); var field = variant.Fields.FirstOrDefault(x => x.Name == expression.Name.Ident);
if (field == null) if (field == null)
throw new CompileException(Diagnostic.Error($"Enum variant '{target.Type}' does not have a field matching the name '{expression.Name.Ident}'").At(fileName, target).Build()); throw BasicError($"Enum variant '{target.Type}' does not have a field matching the name '{expression.Name.Ident}'", target);
return new TypedNodeExpressionMemberAccess(expression.Tokens, field.Type, target, expression.Name); return new TypedNodeExpressionMemberAccess(expression.Tokens, field.Type, target, expression.Name);
} }
default: default:
throw new CompileException(Diagnostic.Error($"{target.Type} has no member '{expression.Name.Ident}'").At(fileName, target).Build()); throw BasicError($"{target.Type} has no member '{expression.Name.Ident}'", target);
} }
} }
@@ -395,7 +395,7 @@ public class TypeChecker
{ {
var target = CheckExpression(expression.Target); var target = CheckExpression(expression.Target);
if (target.Type is not NubTypeFunc funcType) if (target.Type is not NubTypeFunc funcType)
throw new CompileException(Diagnostic.Error($"Cannot invoke function call on type '{target.Type}'").At(fileName, target).Build()); throw BasicError($"Cannot invoke function call on type '{target.Type}'", target);
var parameters = expression.Parameters.Select(CheckExpression).ToList(); var parameters = expression.Parameters.Select(CheckExpression).ToList();
@@ -416,11 +416,11 @@ public class TypeChecker
{ {
var field = info.Fields.FirstOrDefault(x => x.Name == initializer.Name.Ident); var field = info.Fields.FirstOrDefault(x => x.Name == initializer.Name.Ident);
if (field == null) if (field == null)
throw new CompileException(Diagnostic.Error($"Field '{initializer.Name.Ident}' does not exist on struct '{expression.Module.Ident}::{expression.Name.Ident}'").At(fileName, initializer.Name).Build()); throw BasicError($"Field '{initializer.Name.Ident}' does not exist on struct '{expression.Module.Ident}::{expression.Name.Ident}'", initializer.Name);
var value = CheckExpression(initializer.Value); var value = CheckExpression(initializer.Value);
if (!value.Type.IsAssignableTo(field.Type)) if (!value.Type.IsAssignableTo(field.Type))
throw new CompileException(Diagnostic.Error($"Type of assignment ({value.Type}) does not match expected type of field '{field.Name}' ({field.Type})").At(fileName, initializer.Name).Build()); throw BasicError($"Type of assignment ({value.Type}) does not match expected type of field '{field.Name}' ({field.Type})", initializer.Name);
initializers.Add(new TypedNodeExpressionStructLiteral.Initializer(initializer.Tokens, initializer.Name, value)); initializers.Add(new TypedNodeExpressionStructLiteral.Initializer(initializer.Tokens, initializer.Name, value));
} }
@@ -434,18 +434,18 @@ public class TypeChecker
var variant = info.Variants.FirstOrDefault(x => x.Name == expression.VariantName.Ident); var variant = info.Variants.FirstOrDefault(x => x.Name == expression.VariantName.Ident);
if (variant == null) if (variant == null)
throw new CompileException(Diagnostic.Error($"Enum '{expression.Module.Ident}::{expression.EnumName.Ident}' does not have a variant '{expression.VariantName.Ident}'").At(fileName, expression.VariantName).Build()); throw BasicError($"Enum '{expression.Module.Ident}::{expression.EnumName.Ident}' does not have a variant '{expression.VariantName.Ident}'", expression.VariantName);
var initializers = new List<TypedNodeExpressionEnumLiteral.Initializer>(); var initializers = new List<TypedNodeExpressionEnumLiteral.Initializer>();
foreach (var initializer in expression.Initializers) foreach (var initializer in expression.Initializers)
{ {
var field = variant.Fields.FirstOrDefault(x => x.Name == initializer.Name.Ident); var field = variant.Fields.FirstOrDefault(x => x.Name == initializer.Name.Ident);
if (field == null) if (field == null)
throw new CompileException(Diagnostic.Error($"Field '{initializer.Name.Ident}' does not exist on enum variant '{expression.Module.Ident}::{expression.EnumName.Ident}.{expression.VariantName.Ident}'").At(fileName, initializer.Name).Build()); throw BasicError($"Field '{initializer.Name.Ident}' does not exist on enum variant '{expression.Module.Ident}::{expression.EnumName.Ident}.{expression.VariantName.Ident}'", initializer.Name);
var value = CheckExpression(initializer.Value); var value = CheckExpression(initializer.Value);
if (!value.Type.IsAssignableTo(field.Type)) if (!value.Type.IsAssignableTo(field.Type))
throw new CompileException(Diagnostic.Error($"Type of assignment ({value.Type}) does not match expected type of field '{field.Name}' ({field.Type})").At(fileName, initializer.Name).Build()); throw BasicError($"Type of assignment ({value.Type}) does not match expected type of field '{field.Name}' ({field.Type})", initializer.Name);
initializers.Add(new TypedNodeExpressionEnumLiteral.Initializer(initializer.Tokens, initializer.Name, value)); initializers.Add(new TypedNodeExpressionEnumLiteral.Initializer(initializer.Tokens, initializer.Name, value));
} }
@@ -590,6 +590,11 @@ public class TypeChecker
return new CompileException(Diagnostic.Error(message).At(fileName, node).Build()); return new CompileException(Diagnostic.Error(message).At(fileName, node).Build());
} }
private CompileException BasicError(string message, TypedNode node)
{
return new CompileException(Diagnostic.Error(message).At(fileName, node).Build());
}
private sealed class Scope private sealed class Scope
{ {
private readonly Stack<Dictionary<string, NubType>> scopes = new(); private readonly Stack<Dictionary<string, NubType>> scopes = new();