...
This commit is contained in:
@@ -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>();
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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();
|
||||
|
||||
@@ -43,5 +43,7 @@ public enum Symbol
|
||||
Namespace,
|
||||
Let,
|
||||
Alloc,
|
||||
Calls
|
||||
Calls,
|
||||
Interface,
|
||||
Impl
|
||||
}
|
||||
@@ -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()
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
Reference in New Issue
Block a user