This commit is contained in:
nub31
2025-05-26 20:10:22 +02:00
parent 37b4ce3989
commit f63cee1011
5 changed files with 127 additions and 26 deletions

View File

@@ -5,10 +5,10 @@ namespace main
global func main(args: []string) {
i = 0
printf("%d\n", args.count)
c::printf("%d\n", args.count)
while i < args.count {
printf("%s\n", args[i])
c::printf("%s\n", args[i])
i = i + 1
}

View File

@@ -596,7 +596,19 @@ public class Parser
{
if (TryExpectIdentifier(out var name))
{
return NubType.Parse(name);
if (NubPrimitiveType.TryParse(name, out var primitiveTypeKind))
{
return new NubPrimitiveType(primitiveTypeKind.Value);
}
else
{
var @namespace = _namespace;
if (TryExpectSymbol(Symbol.DoubleColon))
{
@namespace = ExpectIdentifier().Value;
}
return new NubStructType(@namespace, name);
}
}
if (TryExpectSymbol(Symbol.Caret))

View File

@@ -10,27 +10,26 @@ public class TypeChecker
private List<Diagnostic> _diagnostics = [];
private NubType? _currentFunctionReturnType;
private bool _hasReturnStatement;
private List<DefinitionNode> _definitions = [];
public DiagnosticsResult<List<DefinitionNode>> TypeCheck(List<SourceFile> sourceFiles)
{
_variables = new Dictionary<string, NubType>();
_diagnostics = [];
_definitions = sourceFiles.SelectMany(x => x.Definitions).ToList();
_currentFunctionReturnType = null;
_hasReturnStatement = false;
_sourceFiles = sourceFiles;
foreach (var structDef in _definitions.OfType<StructDefinitionNode>())
foreach (var structDef in _sourceFiles.SelectMany(f => f.Definitions).OfType<StructDefinitionNode>())
{
TypeCheckStructDef(structDef);
}
foreach (var funcDef in _definitions.OfType<LocalFuncDefinitionNode>())
foreach (var funcDef in _sourceFiles.SelectMany(f => f.Definitions).OfType<LocalFuncDefinitionNode>())
{
TypeCheckFuncDef(funcDef);
}
return new DiagnosticsResult<List<DefinitionNode>>(_diagnostics, _definitions);
return new DiagnosticsResult<List<DefinitionNode>>(_diagnostics, _sourceFiles.SelectMany(f => f.Definitions).ToList());
}
private void TypeCheckStructDef(StructDefinitionNode structDef)
@@ -169,8 +168,16 @@ public class TypeChecker
private NubType? TypeCheckFuncCall(FuncCall funcCall, Node node)
{
var localFuncDef = _definitions.OfType<LocalFuncDefinitionNode>().FirstOrDefault(f => f.Name == funcCall.Name);
var externFuncDef = _definitions.OfType<ExternFuncDefinitionNode>().FirstOrDefault(f => f.Name == funcCall.Name);
List<NubType> parameterTypes = [];
foreach (var funcCallParameter in funcCall.Parameters)
{
var parameterType = TypeCheckExpression(funcCallParameter);
if (parameterType == null) return null;
parameterTypes.Add(parameterType);
}
var localFuncDef = LookupLocalFuncDefinition(funcCall.Namespace, funcCall.Name, parameterTypes);
var externFuncDef = LookupExternFuncDefinition(funcCall.Namespace, funcCall.Name, parameterTypes);
List<FuncParameter> parameters;
Optional<NubType> returnType;
@@ -198,8 +205,7 @@ public class TypeChecker
for (var i = 0; i < funcCall.Parameters.Count; i++)
{
var argType = TypeCheckExpression(funcCall.Parameters[i]);
if (argType == null) continue;
var argType = funcCall.Parameters[i].Type;
NubType paramType;
if (i < parameters.Count)
@@ -420,7 +426,7 @@ public class TypeChecker
return null;
}
var definition = _definitions.OfType<StructDefinitionNode>().FirstOrDefault(s => s.Name == structInit.StructType.Name);
var definition = LookupStructDefinition(customType.Namespace, customType.Name);
if (definition == null)
{
ReportError($"Struct type '{customType.Name}' is not defined", structInit);
@@ -519,7 +525,7 @@ public class TypeChecker
}
case NubStructType structType:
{
var definition = _definitions.OfType<StructDefinitionNode>().FirstOrDefault(s => s.Name == structType.Name);
var definition = LookupStructDefinition(structType.Namespace, structType.Name);
if (definition == null)
{
ReportError($"Struct type '{structType.Name}' is not defined", memberAccess);
@@ -599,4 +605,90 @@ public class TypeChecker
return false;
}
}
private TDefinition? LookupDefinition<TDefinition>(string @namespace, Func<TDefinition, bool> predicate) where TDefinition : DefinitionNode
{
return _sourceFiles
.Where(f => f.Namespace == @namespace)
.SelectMany(f => f.Definitions)
.OfType<TDefinition>()
.FirstOrDefault(predicate);
}
private ExternFuncDefinitionNode? LookupExternFuncDefinition(string @namespace, string name, List<NubType> parameters)
{
return LookupDefinition<ExternFuncDefinitionNode>(@namespace, SignatureMatches);
bool SignatureMatches(ExternFuncDefinitionNode node)
{
if (node.Name != name) return false;
if (node.Parameters.Count == 0 && parameters.Count == 0) return true;
if (node.Parameters.Count > parameters.Count) return false;
for (var i = 0; i < parameters.Count; i++)
{
if (i > node.Parameters.Count)
{
if (node.Parameters[^1].Variadic)
{
if (!AreTypesCompatible(parameters[i], node.Parameters[^1].Type))
{
return false;
}
}
else
{
return false;
}
}
else if (!AreTypesCompatible(parameters[i], node.Parameters[i].Type))
{
return false;
}
}
return true;
}
}
private LocalFuncDefinitionNode? LookupLocalFuncDefinition(string @namespace, string name, List<NubType> parameters)
{
return LookupDefinition<LocalFuncDefinitionNode>(@namespace, SignatureMatches);
bool SignatureMatches(LocalFuncDefinitionNode node)
{
if (node.Name != name) return false;
if (node.Parameters.Count == 0 && parameters.Count == 0) return true;
if (node.Parameters.Count > parameters.Count) return false;
for (var i = 0; i < parameters.Count; i++)
{
if (i > node.Parameters.Count)
{
if (node.Parameters[^1].Variadic)
{
if (!AreTypesCompatible(parameters[i], node.Parameters[^1].Type))
{
return false;
}
}
else
{
return false;
}
}
else if (!AreTypesCompatible(parameters[i], node.Parameters[i].Type))
{
return false;
}
}
return true;
}
}
private StructDefinitionNode? LookupStructDefinition(string @namespace, string name)
{
return LookupDefinition<StructDefinitionNode>(@namespace, d => d.Name == name);
}
}

View File

@@ -11,22 +11,15 @@ public abstract class NubType
public string Name { get; }
public static NubType Parse(string s)
{
if (NubPrimitiveType.TryParse(s, out var kind))
{
return new NubPrimitiveType(kind.Value);
}
return new NubStructType(s);
}
public override bool Equals(object? obj) => obj is NubType item && Name.Equals(item.Name);
public override int GetHashCode() => HashCode.Combine(Name);
public override string ToString() => Name;
}
public class NubStructType(string name) : NubType(name);
public class NubStructType(string name, string @namespace) : NubType(name)
{
public string Namespace { get; } = @namespace;
}
public class NubPointerType(NubType baseType) : NubType("^" + baseType)
{

View File

@@ -30,6 +30,7 @@ internal static class Program
private static int Compile(string srcDir)
{
var error = false;
var lexer = new Lexer();
var parser = new Parser();
var typeChecker = new TypeChecker();
@@ -41,9 +42,11 @@ internal static class Program
var tokenizeResult = lexer.Tokenize(new SourceText(file, content));
tokenizeResult.PrintAllDiagnostics();
error = error || tokenizeResult.HasErrors;
var parseResult = parser.ParseModule(tokenizeResult.Value);
parseResult.PrintAllDiagnostics();
error = error || parseResult.HasErrors;
if (parseResult.Value != null)
{
@@ -53,12 +56,13 @@ internal static class Program
var typeCheckResult = typeChecker.TypeCheck(files);
typeCheckResult.PrintAllDiagnostics();
error = error || typeCheckResult.HasErrors;
var generator = new Generator(typeCheckResult.Value);
var result = generator.Generate();
Console.Out.Write(result);
return 0;
return error ? 1 : 0;
}
}