...
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user