...
This commit is contained in:
@@ -363,12 +363,7 @@ public class Generator
|
||||
private string GenerateFuncCall(FuncCall funcCall)
|
||||
{
|
||||
var parameterDefinitions = _definitions
|
||||
.OfType<LocalFuncDefinitionNode>()
|
||||
.FirstOrDefault(d => d.Name == funcCall.Name)
|
||||
?.Parameters;
|
||||
|
||||
parameterDefinitions ??= _definitions
|
||||
.OfType<ExternFuncDefinitionNode>()
|
||||
.OfType<IFuncSignature>()
|
||||
.FirstOrDefault(d => d.Name == funcCall.Name)
|
||||
?.Parameters;
|
||||
|
||||
|
||||
@@ -5,4 +5,4 @@ namespace Nub.Lang.Frontend.Parsing;
|
||||
public abstract class DefinitionNode(IReadOnlyList<Token> tokens, Optional<string> documentation) : Node(tokens)
|
||||
{
|
||||
public Optional<string> Documentation { get; set; } = documentation;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
using Nub.Lang.Frontend.Lexing;
|
||||
|
||||
namespace Nub.Lang.Frontend.Parsing;
|
||||
|
||||
public class ExternFuncDefinitionNode(IReadOnlyList<Token> tokens, Optional<string> documentation, string name, List<FuncParameter> parameters, Optional<NubType> returnType) : DefinitionNode(tokens, documentation)
|
||||
{
|
||||
public string Name { get; } = name;
|
||||
public List<FuncParameter> Parameters { get; } = parameters;
|
||||
public Optional<NubType> ReturnType { get; } = returnType;
|
||||
|
||||
public override string ToString() => $"{Name}({string.Join(", ", Parameters.Select(p => p.ToString()))}){(ReturnType.HasValue ? ": " + ReturnType.Value : "")}";
|
||||
}
|
||||
32
src/compiler/Nub.Lang/Frontend/Parsing/FuncDefinitionNode.cs
Normal file
32
src/compiler/Nub.Lang/Frontend/Parsing/FuncDefinitionNode.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using Nub.Lang.Frontend.Lexing;
|
||||
|
||||
namespace Nub.Lang.Frontend.Parsing;
|
||||
|
||||
public interface IFuncSignature
|
||||
{
|
||||
public string Name { get; }
|
||||
public List<FuncParameter> Parameters { get; }
|
||||
public Optional<NubType> ReturnType { get; }
|
||||
|
||||
public string ToString() => $"{Name}({string.Join(", ", Parameters.Select(p => p.ToString()))}){(ReturnType.HasValue ? ": " + ReturnType.Value : "")}";
|
||||
}
|
||||
|
||||
public class LocalFuncDefinitionNode(IReadOnlyList<Token> tokens, Optional<string> documentation, string name, List<FuncParameter> parameters, BlockNode body, Optional<NubType> returnType, bool global) : DefinitionNode(tokens, documentation)
|
||||
{
|
||||
public string Name { get; } = name;
|
||||
public List<FuncParameter> Parameters { get; } = parameters;
|
||||
public BlockNode Body { get; } = body;
|
||||
public Optional<NubType> ReturnType { get; } = returnType;
|
||||
public bool Global { get; } = global;
|
||||
|
||||
public override string ToString() => $"{Name}({string.Join(", ", Parameters.Select(p => p.ToString()))}){(ReturnType.HasValue ? ": " + ReturnType.Value : "")}";
|
||||
}
|
||||
|
||||
public class ExternFuncDefinitionNode(IReadOnlyList<Token> tokens, Optional<string> documentation, string name, List<FuncParameter> parameters, Optional<NubType> returnType) : DefinitionNode(tokens, documentation), IFuncSignature
|
||||
{
|
||||
public string Name { get; } = name;
|
||||
public List<FuncParameter> Parameters { get; } = parameters;
|
||||
public Optional<NubType> ReturnType { get; } = returnType;
|
||||
|
||||
public override string ToString() => $"{Name}({string.Join(", ", Parameters.Select(p => p.ToString()))}){(ReturnType.HasValue ? ": " + ReturnType.Value : "")}";
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
using Nub.Lang.Frontend.Lexing;
|
||||
|
||||
namespace Nub.Lang.Frontend.Parsing;
|
||||
|
||||
public class LocalFuncDefinitionNode(IReadOnlyList<Token> tokens, Optional<string> documentation, string name, List<FuncParameter> parameters, BlockNode body, Optional<NubType> returnType, bool global) : DefinitionNode(tokens, documentation)
|
||||
{
|
||||
public string Name { get; } = name;
|
||||
public List<FuncParameter> Parameters { get; } = parameters;
|
||||
public BlockNode Body { get; } = body;
|
||||
public Optional<NubType> ReturnType { get; } = returnType;
|
||||
public bool Global { get; } = global;
|
||||
|
||||
public override string ToString() => $"{Name}({string.Join(", ", Parameters.Select(p => p.ToString()))}){(ReturnType.HasValue ? ": " + ReturnType.Value : "")}";
|
||||
}
|
||||
@@ -176,28 +176,14 @@ public class TypeChecker
|
||||
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;
|
||||
if (localFuncDef != null)
|
||||
{
|
||||
parameters = localFuncDef.Parameters;
|
||||
returnType = localFuncDef.ReturnType;
|
||||
}
|
||||
else if (externFuncDef != null)
|
||||
{
|
||||
parameters = externFuncDef.Parameters;
|
||||
returnType = externFuncDef.ReturnType;
|
||||
}
|
||||
else
|
||||
var funcDefinition = LookupFuncSignature(funcCall.Namespace, funcCall.Name, parameterTypes);
|
||||
if (funcDefinition == null)
|
||||
{
|
||||
ReportError($"Function '{funcCall.Name}' is not defined", node);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (parameters.Take(parameters.Count - 1).Any(x => x.Variadic))
|
||||
if (funcDefinition.Parameters.Take(funcDefinition.Parameters.Count - 1).Any(x => x.Variadic))
|
||||
{
|
||||
ReportError($"Function '{funcCall.Name}' has multiple variadic parameters", node);
|
||||
return null;
|
||||
@@ -208,13 +194,13 @@ public class TypeChecker
|
||||
var argType = funcCall.Parameters[i].Type;
|
||||
|
||||
NubType paramType;
|
||||
if (i < parameters.Count)
|
||||
if (i < funcDefinition.Parameters.Count)
|
||||
{
|
||||
paramType = parameters[i].Type;
|
||||
paramType = funcDefinition.Parameters[i].Type;
|
||||
}
|
||||
else if (parameters.LastOrDefault()?.Variadic ?? false)
|
||||
else if (funcDefinition.Parameters.LastOrDefault()?.Variadic ?? false)
|
||||
{
|
||||
paramType = parameters[^1].Type;
|
||||
paramType = funcDefinition.Parameters[^1].Type;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -228,7 +214,7 @@ public class TypeChecker
|
||||
}
|
||||
}
|
||||
|
||||
return returnType.HasValue ? returnType.Value : NubPrimitiveType.Any;
|
||||
return funcDefinition.ReturnType.HasValue ? funcDefinition.ReturnType.Value : NubPrimitiveType.Any;
|
||||
}
|
||||
|
||||
private void TypeCheckIf(IfNode ifNode)
|
||||
@@ -606,56 +592,15 @@ public class TypeChecker
|
||||
}
|
||||
}
|
||||
|
||||
private TDefinition? LookupDefinition<TDefinition>(string @namespace, Func<TDefinition, bool> predicate) where TDefinition : DefinitionNode
|
||||
private IFuncSignature? LookupFuncSignature(string @namespace, string name, List<NubType> parameters)
|
||||
{
|
||||
return _sourceFiles
|
||||
.Where(f => f.Namespace == @namespace)
|
||||
.SelectMany(f => f.Definitions)
|
||||
.OfType<TDefinition>()
|
||||
.FirstOrDefault(predicate);
|
||||
}
|
||||
.OfType<IFuncSignature>()
|
||||
.FirstOrDefault(SignatureMatches);
|
||||
|
||||
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)
|
||||
bool SignatureMatches(IFuncSignature node)
|
||||
{
|
||||
if (node.Name != name) return false;
|
||||
if (node.Parameters.Count == 0 && parameters.Count == 0) return true;
|
||||
@@ -689,6 +634,10 @@ public class TypeChecker
|
||||
|
||||
private StructDefinitionNode? LookupStructDefinition(string @namespace, string name)
|
||||
{
|
||||
return LookupDefinition<StructDefinitionNode>(@namespace, d => d.Name == name);
|
||||
return _sourceFiles
|
||||
.Where(f => f.Namespace == @namespace)
|
||||
.SelectMany(f => f.Definitions)
|
||||
.OfType<StructDefinitionNode>()
|
||||
.FirstOrDefault(d => d.Name == name);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user