This commit is contained in:
nub31
2025-07-04 17:48:56 +02:00
parent 9a21ec5d8d
commit cea72bf846
11 changed files with 346 additions and 78 deletions

View File

@@ -50,6 +50,34 @@ public class DefinitionTable
.SelectMany(c => c.Definitions)
.OfType<FuncDefinition>();
}
public IEnumerable<LocalFuncDefinitionNode> GetLocalFunctions()
{
return _syntaxTrees
.SelectMany(c => c.Definitions)
.OfType<LocalFuncDefinitionNode>();
}
public IEnumerable<ExternFuncDefinitionNode> GetExternFunctions()
{
return _syntaxTrees
.SelectMany(c => c.Definitions)
.OfType<ExternFuncDefinitionNode>();
}
public IEnumerable<InterfaceDefinitionNode> GetInterfaces()
{
return _syntaxTrees
.SelectMany(c => c.Definitions)
.OfType<InterfaceDefinitionNode>();
}
public IEnumerable<ImplementationDefinitionNode> GetImplementations()
{
return _syntaxTrees
.SelectMany(c => c.Definitions)
.OfType<ImplementationDefinitionNode>();
}
}
public class BoundDefinitionTable
@@ -96,4 +124,32 @@ public class BoundDefinitionTable
.SelectMany(c => c.Definitions)
.OfType<BoundFuncDefinition>();
}
public IEnumerable<BoundLocalFuncDefinitionNode> GetLocalFunctions()
{
return _syntaxTrees
.SelectMany(c => c.Definitions)
.OfType<BoundLocalFuncDefinitionNode>();
}
public IEnumerable<BoundExternFuncDefinitionNode> GetExternFunctions()
{
return _syntaxTrees
.SelectMany(c => c.Definitions)
.OfType<BoundExternFuncDefinitionNode>();
}
public IEnumerable<BoundInterfaceDefinitionNode> GetInterfaces()
{
return _syntaxTrees
.SelectMany(c => c.Definitions)
.OfType<BoundInterfaceDefinitionNode>();
}
public IEnumerable<BoundImplementationDefinitionNode> GetImplementations()
{
return _syntaxTrees
.SelectMany(c => c.Definitions)
.OfType<BoundImplementationDefinitionNode>();
}
}

View File

@@ -13,3 +13,9 @@ public record ExternFuncDefinitionNode(IEnumerable<Token> Tokens, Optional<strin
public record StructField(string Name, NubType Type, Optional<ExpressionNode> Value);
public record StructDefinitionNode(IEnumerable<Token> Tokens, Optional<string> Documentation, string Namespace, string Name, List<StructField> Fields) : DefinitionNode(Tokens, Documentation, Namespace);
public record InterfaceFunc(string Name, List<FuncParameter> Parameters, NubType ReturnType);
public record InterfaceDefinitionNode(IEnumerable<Token> Tokens, Optional<string> Documentation, string Namespace, string Name, List<InterfaceFunc> Functions) : DefinitionNode(Tokens, Documentation, Namespace);
public record ImplementationFunc(string Name, List<FuncParameter> Parameters, NubType ReturnType, BlockNode Body);
public record ImplementationDefinitionNode(IEnumerable<Token> Tokens, Optional<string> Documentation, string Namespace, NubType Type, NubType Interface, List<ImplementationFunc> Functions) : DefinitionNode(Tokens, Documentation, Namespace);

View File

@@ -81,6 +81,8 @@ public static class Parser
{
Symbol.Func => ParseFuncDefinition(startIndex, modifiers, Optional.OfNullable(documentation)),
Symbol.Struct => ParseStruct(startIndex, modifiers, Optional.OfNullable(documentation)),
Symbol.Interface => ParseInterface(startIndex, modifiers, Optional.OfNullable(documentation)),
Symbol.Impl => ParseImplementation(startIndex, modifiers, Optional.OfNullable(documentation)),
_ => throw new ParseException(Diagnostic
.Error($"Expected 'func' or 'struct', but found '{keyword.Symbol}'")
.WithHelp("Valid definition keywords are 'func' and 'struct'")
@@ -149,7 +151,7 @@ public static class Parser
return new LocalFuncDefinitionNode(GetTokensForNode(startIndex), documentation, _namespace, name.Value, parameters, body, returnType, exported);
}
private static StructDefinitionNode ParseStruct(int startIndex, List<ModifierToken> _, Optional<string> documentation)
private static StructDefinitionNode ParseStruct(int startIndex, List<ModifierToken> modifiers, Optional<string> documentation)
{
var name = ExpectIdentifier().Value;
@@ -173,9 +175,109 @@ public static class Parser
variables.Add(new StructField(variableName, variableType, variableValue));
}
if (modifiers.Count != 0)
{
throw new ParseException(Diagnostic
.Error($"Invalid modifiers for struct: {modifiers[0].Modifier}")
.WithHelp($"Structs cannot use the '{modifiers[0].Modifier}' modifier")
.At(modifiers[0])
.Build());
}
return new StructDefinitionNode(GetTokensForNode(startIndex), documentation, _namespace, name, variables);
}
private static InterfaceDefinitionNode ParseInterface(int startIndex, List<ModifierToken> modifiers, Optional<string> documentation)
{
var name = ExpectIdentifier().Value;
ExpectSymbol(Symbol.OpenBrace);
List<InterfaceFunc> functions = [];
while (!TryExpectSymbol(Symbol.CloseBrace))
{
ExpectSymbol(Symbol.Func);
var funcName = ExpectIdentifier().Value;
var parameters = new List<FuncParameter>();
ExpectSymbol(Symbol.OpenParen);
while (!TryExpectSymbol(Symbol.CloseParen))
{
var parameter = ParseFuncParameter();
parameters.Add(parameter);
if (!TryExpectSymbol(Symbol.Comma) && Peek().TryGetValue(out var nextToken) && nextToken is not SymbolToken { Symbol: Symbol.CloseParen })
{
_diagnostics.Add(Diagnostic
.Warning("Missing comma between function arguments")
.WithHelp("Add a ',' to separate arguments")
.At(nextToken)
.Build());
}
}
var returnType = TryExpectSymbol(Symbol.Colon) ? ParseType() : new NubVoidType();
if (modifiers.Count != 0)
{
throw new ParseException(Diagnostic
.Error($"Invalid modifiers for interface: {modifiers[0].Modifier}")
.WithHelp($"Interface cannot use the '{modifiers[0].Modifier}' modifier")
.At(modifiers[0])
.Build());
}
functions.Add(new InterfaceFunc(funcName, parameters, returnType));
}
return new InterfaceDefinitionNode(GetTokensForNode(startIndex), documentation, _namespace, name, functions);
}
private static ImplementationDefinitionNode ParseImplementation(int startIndex, List<ModifierToken> modifiers, Optional<string> documentation)
{
var type = ParseType();
ExpectSymbol(Symbol.Colon);
var @interface = ParseType();
List<ImplementationFunc> functions = [];
ExpectSymbol(Symbol.OpenBrace);
while (!TryExpectSymbol(Symbol.CloseBrace))
{
ExpectSymbol(Symbol.Func);
var functionName = ExpectIdentifier().Value;
var parameters = new List<FuncParameter>
{
new("this", type)
};
ExpectSymbol(Symbol.OpenParen);
while (!TryExpectSymbol(Symbol.CloseParen))
{
parameters.Add(ParseFuncParameter());
if (!TryExpectSymbol(Symbol.Comma) && Peek().TryGetValue(out var token) && token is not SymbolToken { Symbol: Symbol.CloseParen })
{
_diagnostics.Add(Diagnostic
.Warning("Missing comma between function parameters")
.WithHelp("Add a ',' to separate parameters")
.At(token)
.Build());
}
}
var returnType = TryExpectSymbol(Symbol.Colon) ? ParseType() : new NubVoidType();
var body = ParseBlock();
functions.AddRange(new ImplementationFunc(functionName, parameters, returnType, body));
}
return new ImplementationDefinitionNode(GetTokensForNode(startIndex), documentation, _namespace, type, @interface, functions);
}
private static FuncParameter ParseFuncParameter()
{
var name = ExpectIdentifier();

View File

@@ -43,5 +43,7 @@ public enum Symbol
Namespace,
Let,
Alloc,
Calls
Calls,
Interface,
Impl
}

View File

@@ -19,6 +19,8 @@ public static class Tokenizer
["struct"] = Symbol.Struct,
["let"] = Symbol.Let,
["calls"] = Symbol.Calls,
["interface"] = Symbol.Interface,
["impl"] = Symbol.Impl,
};
private static readonly Dictionary<string, Modifier> Modifiers = new()

View File

@@ -41,12 +41,53 @@ public static class Binder
return node switch
{
ExternFuncDefinitionNode definition => BindExternFuncDefinition(definition),
ImplementationDefinitionNode definition => BindImplementation(definition),
InterfaceDefinitionNode definition => BindInterfaceDefinition(definition),
LocalFuncDefinitionNode definition => BindLocalFuncDefinition(definition),
StructDefinitionNode definition => BindStruct(definition),
_ => throw new ArgumentOutOfRangeException(nameof(node))
};
}
private static BoundImplementationDefinitionNode BindImplementation(ImplementationDefinitionNode node)
{
_variables.Clear();
var functions = new List<BoundImplementationFunc>();
foreach (var function in node.Functions)
{
var parameters = new List<BoundFuncParameter>();
foreach (var parameter in function.Parameters)
{
parameters.Add(new BoundFuncParameter(parameter.Name, parameter.Type));
_variables[parameter.Name] = parameter.Type;
}
functions.Add(new BoundImplementationFunc(function.Name, parameters, function.ReturnType, BindBlock(function.Body)));
}
return new BoundImplementationDefinitionNode(node.Tokens, node.Documentation, node.Namespace, node.Type, node.Interface, functions);
}
private static BoundInterfaceDefinitionNode BindInterfaceDefinition(InterfaceDefinitionNode node)
{
var functions = new List<BoundInterfaceFunc>();
foreach (var func in node.Functions)
{
var parameters = new List<BoundFuncParameter>();
foreach (var parameter in func.Parameters)
{
parameters.Add(new BoundFuncParameter(parameter.Name, parameter.Type));
}
functions.Add(new BoundInterfaceFunc(func.Name, parameters, func.ReturnType));
}
return new BoundInterfaceDefinitionNode(node.Tokens, node.Documentation, node.Namespace, node.Name, functions);
}
private static BoundStructDefinitionNode BindStruct(StructDefinitionNode node)
{
var defOpt = _definitionTable.LookupStruct(node.Namespace, node.Name);
@@ -354,6 +395,12 @@ public static class Binder
NubType? type = null;
var implementation = _definitionTable.GetImplementations().FirstOrDefault(x => x.Type.Equals(boundExpression.Type));
if (implementation != null)
{
if (implementation.Interface.)
}
switch (boundExpression.Type)
{
case NubArrayType:

View File

@@ -12,3 +12,9 @@ public record BoundExternFuncDefinitionNode(IEnumerable<Token> Tokens, Optional<
public record BoundStructField(string Name, NubType Type, Optional<BoundExpressionNode> Value);
public record BoundStructDefinitionNode(IEnumerable<Token> Tokens, Optional<string> Documentation, string Namespace, string Name, List<BoundStructField> Fields) : BoundDefinitionNode(Tokens, Documentation, Namespace);
public record BoundInterfaceFunc(string Name, List<BoundFuncParameter> Parameters, NubType ReturnType);
public record BoundInterfaceDefinitionNode(IEnumerable<Token> Tokens, Optional<string> Documentation, string Namespace, string Name, List<BoundInterfaceFunc> Functions) : BoundDefinitionNode(Tokens, Documentation, Namespace);
public record BoundImplementationFunc(string Name, List<BoundFuncParameter> Parameters, NubType ReturnType, BoundBlockNode Body);
public record BoundImplementationDefinitionNode(IEnumerable<Token> Tokens, Optional<string> Documentation, string Namespace, NubType Type, NubInterfaceType Interface, List<BoundImplementationFunc> Functions) : BoundDefinitionNode(Tokens, Documentation, Namespace);