...
This commit is contained in:
@@ -363,12 +363,7 @@ public class Generator
|
|||||||
private string GenerateFuncCall(FuncCall funcCall)
|
private string GenerateFuncCall(FuncCall funcCall)
|
||||||
{
|
{
|
||||||
var parameterDefinitions = _definitions
|
var parameterDefinitions = _definitions
|
||||||
.OfType<LocalFuncDefinitionNode>()
|
.OfType<IFuncSignature>()
|
||||||
.FirstOrDefault(d => d.Name == funcCall.Name)
|
|
||||||
?.Parameters;
|
|
||||||
|
|
||||||
parameterDefinitions ??= _definitions
|
|
||||||
.OfType<ExternFuncDefinitionNode>()
|
|
||||||
.FirstOrDefault(d => d.Name == funcCall.Name)
|
.FirstOrDefault(d => d.Name == funcCall.Name)
|
||||||
?.Parameters;
|
?.Parameters;
|
||||||
|
|
||||||
|
|||||||
@@ -5,4 +5,4 @@ namespace Nub.Lang.Frontend.Parsing;
|
|||||||
public abstract class DefinitionNode(IReadOnlyList<Token> tokens, Optional<string> documentation) : Node(tokens)
|
public abstract class DefinitionNode(IReadOnlyList<Token> tokens, Optional<string> documentation) : Node(tokens)
|
||||||
{
|
{
|
||||||
public Optional<string> Documentation { get; set; } = documentation;
|
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);
|
parameterTypes.Add(parameterType);
|
||||||
}
|
}
|
||||||
|
|
||||||
var localFuncDef = LookupLocalFuncDefinition(funcCall.Namespace, funcCall.Name, parameterTypes);
|
var funcDefinition = LookupFuncSignature(funcCall.Namespace, funcCall.Name, parameterTypes);
|
||||||
var externFuncDef = LookupExternFuncDefinition(funcCall.Namespace, funcCall.Name, parameterTypes);
|
if (funcDefinition == null)
|
||||||
|
|
||||||
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
|
|
||||||
{
|
{
|
||||||
ReportError($"Function '{funcCall.Name}' is not defined", node);
|
ReportError($"Function '{funcCall.Name}' is not defined", node);
|
||||||
return null;
|
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);
|
ReportError($"Function '{funcCall.Name}' has multiple variadic parameters", node);
|
||||||
return null;
|
return null;
|
||||||
@@ -208,13 +194,13 @@ public class TypeChecker
|
|||||||
var argType = funcCall.Parameters[i].Type;
|
var argType = funcCall.Parameters[i].Type;
|
||||||
|
|
||||||
NubType paramType;
|
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
|
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)
|
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
|
return _sourceFiles
|
||||||
.Where(f => f.Namespace == @namespace)
|
.Where(f => f.Namespace == @namespace)
|
||||||
.SelectMany(f => f.Definitions)
|
.SelectMany(f => f.Definitions)
|
||||||
.OfType<TDefinition>()
|
.OfType<IFuncSignature>()
|
||||||
.FirstOrDefault(predicate);
|
.FirstOrDefault(SignatureMatches);
|
||||||
}
|
|
||||||
|
|
||||||
private ExternFuncDefinitionNode? LookupExternFuncDefinition(string @namespace, string name, List<NubType> parameters)
|
bool SignatureMatches(IFuncSignature node)
|
||||||
{
|
|
||||||
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.Name != name) return false;
|
||||||
if (node.Parameters.Count == 0 && parameters.Count == 0) return true;
|
if (node.Parameters.Count == 0 && parameters.Count == 0) return true;
|
||||||
@@ -689,6 +634,10 @@ public class TypeChecker
|
|||||||
|
|
||||||
private StructDefinitionNode? LookupStructDefinition(string @namespace, string name)
|
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