...
This commit is contained in:
@@ -81,12 +81,11 @@ foreach (var file in options.Files)
|
|||||||
foreach (var file in options.Files)
|
foreach (var file in options.Files)
|
||||||
{
|
{
|
||||||
var tokenizer = new Tokenizer(file.GetText());
|
var tokenizer = new Tokenizer(file.GetText());
|
||||||
var tokenizeResult = tokenizer.Tokenize(out var tokenizerDiagnostics);
|
var tokens = tokenizer.Tokenize();
|
||||||
diagnostics.AddRange(tokenizerDiagnostics);
|
|
||||||
|
|
||||||
var parser = new Parser(tokenizeResult);
|
var parser = new Parser();
|
||||||
var syntaxTree = parser.Parse(out var parserDiagnostics);
|
var syntaxTree = parser.Parse(tokens);
|
||||||
diagnostics.AddRange(parserDiagnostics);
|
diagnostics.AddRange(parser.GetDiagnostics());
|
||||||
|
|
||||||
syntaxTrees.Add(syntaxTree);
|
syntaxTrees.Add(syntaxTree);
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
@@ -12,25 +12,25 @@ public sealed class BoundDefinitionTable
|
|||||||
_definitions = syntaxTrees.SelectMany(x => x.Definitions).ToList();
|
_definitions = syntaxTrees.SelectMany(x => x.Definitions).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public BoundLocalFunc LookupLocalFunc(string @namespace, string name)
|
public BoundLocalFunc LookupLocalFunc(string name)
|
||||||
{
|
{
|
||||||
return _definitions
|
return _definitions
|
||||||
.OfType<BoundLocalFunc>()
|
.OfType<BoundLocalFunc>()
|
||||||
.First(x => x.Namespace == @namespace && x.Name == name);
|
.First(x => x.Name == name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BoundExternFunc LookupExternFunc(string @namespace, string name)
|
public BoundExternFunc LookupExternFunc(string name)
|
||||||
{
|
{
|
||||||
return _definitions
|
return _definitions
|
||||||
.OfType<BoundExternFunc>()
|
.OfType<BoundExternFunc>()
|
||||||
.First(x => x.Namespace == @namespace && x.Name == name);
|
.First(x => x.Name == name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BoundStruct LookupStruct(string @namespace, string name)
|
public BoundStruct LookupStruct(string name)
|
||||||
{
|
{
|
||||||
return _definitions
|
return _definitions
|
||||||
.OfType<BoundStruct>()
|
.OfType<BoundStruct>()
|
||||||
.First(x => x.Namespace == @namespace && x.Name == name);
|
.First(x => x.Name == name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BoundStructField LookupStructField(BoundStruct @struct, string field)
|
public BoundStructField LookupStructField(BoundStruct @struct, string field)
|
||||||
@@ -54,11 +54,11 @@ public sealed class BoundDefinitionTable
|
|||||||
.First(x => x.Name == name);
|
.First(x => x.Name == name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BoundTrait LookupTrait(string @namespace, string name)
|
public BoundTrait LookupTrait(string name)
|
||||||
{
|
{
|
||||||
return _definitions
|
return _definitions
|
||||||
.OfType<BoundTrait>()
|
.OfType<BoundTrait>()
|
||||||
.First(x => x.Namespace == @namespace && x.Name == name);
|
.First(x => x.Name == name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BoundTraitFunc LookupTraitFunc(BoundTrait trait, string name)
|
public BoundTraitFunc LookupTraitFunc(BoundTrait trait, string name)
|
||||||
|
|||||||
@@ -224,13 +224,13 @@ public partial class QBEGenerator
|
|||||||
|
|
||||||
private Val EmitExternFuncIdent(BoundExternFuncIdent externFuncIdent)
|
private Val EmitExternFuncIdent(BoundExternFuncIdent externFuncIdent)
|
||||||
{
|
{
|
||||||
var func = _definitionTable.LookupExternFunc(externFuncIdent.Namespace, externFuncIdent.Name);
|
var func = _definitionTable.LookupExternFunc(externFuncIdent.Name);
|
||||||
return new Val(ExternFuncName(func), externFuncIdent.Type, ValKind.Direct);
|
return new Val(ExternFuncName(func), externFuncIdent.Type, ValKind.Direct);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Val EmitLocalFuncIdent(BoundLocalFuncIdent localFuncIdent)
|
private Val EmitLocalFuncIdent(BoundLocalFuncIdent localFuncIdent)
|
||||||
{
|
{
|
||||||
var func = _definitionTable.LookupLocalFunc(localFuncIdent.Namespace, localFuncIdent.Name);
|
var func = _definitionTable.LookupLocalFunc(localFuncIdent.Name);
|
||||||
return new Val(LocalFuncName(func), localFuncIdent.Type, ValKind.Direct);
|
return new Val(LocalFuncName(func), localFuncIdent.Type, ValKind.Direct);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -323,7 +323,7 @@ public partial class QBEGenerator
|
|||||||
|
|
||||||
private Val EmitStructInitializer(BoundStructInitializer structInitializer, string? destination = null)
|
private Val EmitStructInitializer(BoundStructInitializer structInitializer, string? destination = null)
|
||||||
{
|
{
|
||||||
var @struct = _definitionTable.LookupStruct(structInitializer.StructType.Namespace, structInitializer.StructType.Name);
|
var @struct = _definitionTable.LookupStruct(structInitializer.StructType.Name);
|
||||||
|
|
||||||
if (destination == null)
|
if (destination == null)
|
||||||
{
|
{
|
||||||
@@ -400,7 +400,7 @@ public partial class QBEGenerator
|
|||||||
{
|
{
|
||||||
var target = EmitUnwrap(EmitExpression(structFieldAccess.Target));
|
var target = EmitUnwrap(EmitExpression(structFieldAccess.Target));
|
||||||
|
|
||||||
var structDef = _definitionTable.LookupStruct(structFieldAccess.StructType.Namespace, structFieldAccess.StructType.Name);
|
var structDef = _definitionTable.LookupStruct(structFieldAccess.StructType.Name);
|
||||||
var offset = OffsetOf(structDef, structFieldAccess.Field);
|
var offset = OffsetOf(structDef, structFieldAccess.Field);
|
||||||
|
|
||||||
var output = TmpName();
|
var output = TmpName();
|
||||||
|
|||||||
@@ -373,7 +373,7 @@ public partial class QBEGenerator
|
|||||||
|
|
||||||
private void EmitStructDefinition(BoundStruct structDef)
|
private void EmitStructDefinition(BoundStruct structDef)
|
||||||
{
|
{
|
||||||
_writer.WriteLine($"type {CustomTypeName(structDef.Namespace, structDef.Name)} = {{ ");
|
_writer.WriteLine($"type {CustomTypeName(structDef.Name)} = {{ ");
|
||||||
|
|
||||||
var types = new Dictionary<string, string>();
|
var types = new Dictionary<string, string>();
|
||||||
|
|
||||||
@@ -419,7 +419,7 @@ public partial class QBEGenerator
|
|||||||
|
|
||||||
private void EmitTraitVTable(BoundTrait traitDef)
|
private void EmitTraitVTable(BoundTrait traitDef)
|
||||||
{
|
{
|
||||||
_writer.WriteLine($"type {CustomTypeName(traitDef.Namespace, traitDef.Name)} = {{");
|
_writer.WriteLine($"type {CustomTypeName(traitDef.Name)} = {{");
|
||||||
|
|
||||||
foreach (var func in traitDef.Functions)
|
foreach (var func in traitDef.Functions)
|
||||||
{
|
{
|
||||||
@@ -500,7 +500,7 @@ public partial class QBEGenerator
|
|||||||
|
|
||||||
private string LocalFuncName(BoundLocalFunc funcDef)
|
private string LocalFuncName(BoundLocalFunc funcDef)
|
||||||
{
|
{
|
||||||
return $"${funcDef.Namespace}_{funcDef.Name}";
|
return $"${funcDef.Name}";
|
||||||
}
|
}
|
||||||
|
|
||||||
private string ExternFuncName(BoundExternFunc funcDef)
|
private string ExternFuncName(BoundExternFunc funcDef)
|
||||||
@@ -510,12 +510,12 @@ public partial class QBEGenerator
|
|||||||
|
|
||||||
private string CustomTypeName(NubCustomType customType)
|
private string CustomTypeName(NubCustomType customType)
|
||||||
{
|
{
|
||||||
return CustomTypeName(customType.Namespace, customType.Name);
|
return CustomTypeName(customType.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
private string CustomTypeName(string @namespace, string name)
|
private string CustomTypeName(string name)
|
||||||
{
|
{
|
||||||
return $":{@namespace}_{name}";
|
return $":{name}";
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ public sealed class Binder
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new BoundSyntaxTree(_syntaxTree.Namespace, definitions, diagnostics);
|
return new BoundSyntaxTree(definitions, diagnostics);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundDefinition BindDefinition(DefinitionSyntax node)
|
private BoundDefinition BindDefinition(DefinitionSyntax node)
|
||||||
@@ -66,7 +66,7 @@ public sealed class Binder
|
|||||||
functions.Add(new BoundTraitFunc(function.Name, BindFuncSignature(function.Signature)));
|
functions.Add(new BoundTraitFunc(function.Name, BindFuncSignature(function.Signature)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new BoundTrait(node.Namespace, node.Name, functions);
|
return new BoundTrait(node.Name, functions);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundStruct BindStruct(StructSyntax node)
|
private BoundStruct BindStruct(StructSyntax node)
|
||||||
@@ -85,12 +85,12 @@ public sealed class Binder
|
|||||||
structFields.Add(new BoundStructField(field.Index, field.Name, BindType(field.Type), value));
|
structFields.Add(new BoundStructField(field.Index, field.Name, BindType(field.Type), value));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new BoundStruct(node.Namespace, node.Name, structFields);
|
return new BoundStruct(node.Name, structFields);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundExternFunc BindExternFuncDefinition(ExternFuncSyntax node)
|
private BoundExternFunc BindExternFuncDefinition(ExternFuncSyntax node)
|
||||||
{
|
{
|
||||||
return new BoundExternFunc(node.Namespace, node.Name, node.CallName, BindFuncSignature(node.Signature));
|
return new BoundExternFunc(node.Name, node.CallName, BindFuncSignature(node.Signature));
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundLocalFunc BindLocalFuncDefinition(LocalFuncSyntax node)
|
private BoundLocalFunc BindLocalFuncDefinition(LocalFuncSyntax node)
|
||||||
@@ -98,7 +98,7 @@ public sealed class Binder
|
|||||||
var signature = BindFuncSignature(node.Signature);
|
var signature = BindFuncSignature(node.Signature);
|
||||||
var body = BindFuncBody(node.Body, signature.ReturnType, signature.Parameters);
|
var body = BindFuncBody(node.Body, signature.ReturnType, signature.Parameters);
|
||||||
|
|
||||||
return new BoundLocalFunc(node.Namespace, node.Name, signature, body);
|
return new BoundLocalFunc(node.Name, signature, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundStatement BindStatement(StatementSyntax node)
|
private BoundStatement BindStatement(StatementSyntax node)
|
||||||
@@ -299,13 +299,18 @@ public sealed class Binder
|
|||||||
|
|
||||||
private BoundExpression BindIdentifier(IdentifierSyntax expression)
|
private BoundExpression BindIdentifier(IdentifierSyntax expression)
|
||||||
{
|
{
|
||||||
var @namespace = expression.Namespace.Or(_syntaxTree.Namespace);
|
var variable = Scope.Lookup(expression.Name);
|
||||||
var localFuncs = _definitionTable.LookupLocalFunc(@namespace, expression.Name).ToArray();
|
if (variable != null)
|
||||||
|
{
|
||||||
|
return new BoundVariableIdent(variable.Type, variable.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
var localFuncs = _definitionTable.LookupLocalFunc(expression.Name).ToArray();
|
||||||
if (localFuncs.Length > 0)
|
if (localFuncs.Length > 0)
|
||||||
{
|
{
|
||||||
if (localFuncs.Length > 1)
|
if (localFuncs.Length > 1)
|
||||||
{
|
{
|
||||||
throw new BindException(Diagnostic.Error($"Extern func {expression.Namespace}::{expression.Name} has multiple definitions").Build());
|
throw new BindException(Diagnostic.Error($"Extern func {expression.Name} has multiple definitions").Build());
|
||||||
}
|
}
|
||||||
|
|
||||||
var localFunc = localFuncs[0];
|
var localFunc = localFuncs[0];
|
||||||
@@ -313,15 +318,15 @@ public sealed class Binder
|
|||||||
var returnType = BindType(localFunc.Signature.ReturnType);
|
var returnType = BindType(localFunc.Signature.ReturnType);
|
||||||
var parameterTypes = localFunc.Signature.Parameters.Select(p => BindType(p.Type)).ToList();
|
var parameterTypes = localFunc.Signature.Parameters.Select(p => BindType(p.Type)).ToList();
|
||||||
var type = new NubFuncType(parameterTypes, returnType);
|
var type = new NubFuncType(parameterTypes, returnType);
|
||||||
return new BoundLocalFuncIdent(type, @namespace, expression.Name);
|
return new BoundLocalFuncIdent(type, expression.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
var externFuncs = _definitionTable.LookupExternFunc(@namespace, expression.Name).ToArray();
|
var externFuncs = _definitionTable.LookupExternFunc(expression.Name).ToArray();
|
||||||
if (externFuncs.Length > 0)
|
if (externFuncs.Length > 0)
|
||||||
{
|
{
|
||||||
if (externFuncs.Length > 1)
|
if (externFuncs.Length > 1)
|
||||||
{
|
{
|
||||||
throw new BindException(Diagnostic.Error($"Extern func {expression.Namespace}::{expression.Name} has multiple definitions").Build());
|
throw new BindException(Diagnostic.Error($"Extern func {expression.Name} has multiple definitions").Build());
|
||||||
}
|
}
|
||||||
|
|
||||||
var externFunc = externFuncs[0];
|
var externFunc = externFuncs[0];
|
||||||
@@ -329,19 +334,10 @@ public sealed class Binder
|
|||||||
var returnType = BindType(externFunc.Signature.ReturnType);
|
var returnType = BindType(externFunc.Signature.ReturnType);
|
||||||
var parameterTypes = externFunc.Signature.Parameters.Select(p => BindType(p.Type)).ToList();
|
var parameterTypes = externFunc.Signature.Parameters.Select(p => BindType(p.Type)).ToList();
|
||||||
var type = new NubFuncType(parameterTypes, returnType);
|
var type = new NubFuncType(parameterTypes, returnType);
|
||||||
return new BoundExternFuncIdent(type, @namespace, expression.Name);
|
return new BoundExternFuncIdent(type, expression.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!expression.Namespace.HasValue)
|
throw new BindException(Diagnostic.Error($"No identifier with the name {expression.Name} exists").Build());
|
||||||
{
|
|
||||||
var variable = Scope.Lookup(expression.Name);
|
|
||||||
if (variable != null)
|
|
||||||
{
|
|
||||||
return new BoundVariableIdent(variable.Type, variable.Name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new BindException(Diagnostic.Error($"No identifier with the name {(expression.Namespace.HasValue ? $"{expression.Namespace.Value}::" : "")}{expression.Name} exists").Build());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundLiteral BindLiteral(LiteralSyntax expression, NubType? expectedType = null)
|
private BoundLiteral BindLiteral(LiteralSyntax expression, NubType? expectedType = null)
|
||||||
@@ -362,22 +358,6 @@ public sealed class Binder
|
|||||||
{
|
{
|
||||||
var boundExpression = BindExpression(expression.Target);
|
var boundExpression = BindExpression(expression.Target);
|
||||||
|
|
||||||
// var traitFuncImpls = _definitionTable.LookupTraitFuncImpl(boundExpression.Type, expression.Member).ToArray();
|
|
||||||
// if (traitFuncImpls.Length > 0)
|
|
||||||
// {
|
|
||||||
// if (traitFuncImpls.Length > 1)
|
|
||||||
// {
|
|
||||||
// throw new BindException(Diagnostic.Error($"Type {boundExpression.Type} implements multiple traits with the function {expression.Member}").Build());
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// var impl = traitFuncImpls[0];
|
|
||||||
//
|
|
||||||
// var returnType = BindType(impl.Signature.ReturnType);
|
|
||||||
// var parameterTypes = impl.Signature.Parameters.Select(p => BindType(p.Type)).ToList();
|
|
||||||
// var type = new NubFuncType(parameterTypes, returnType);
|
|
||||||
// return new BoundTraitImplFuncAccess(type, boundExpression, expression.Member);
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (boundExpression.Type is NubCustomType customType)
|
if (boundExpression.Type is NubCustomType customType)
|
||||||
{
|
{
|
||||||
var traits = _definitionTable.LookupTrait(customType).ToArray();
|
var traits = _definitionTable.LookupTrait(customType).ToArray();
|
||||||
@@ -593,7 +573,7 @@ public sealed class Binder
|
|||||||
{
|
{
|
||||||
ArrayTypeSyntax type => new NubArrayType(BindType(type.BaseType)),
|
ArrayTypeSyntax type => new NubArrayType(BindType(type.BaseType)),
|
||||||
CStringTypeSyntax => new NubCStringType(),
|
CStringTypeSyntax => new NubCStringType(),
|
||||||
CustomTypeSyntax type => new NubCustomType(type.Namespace, type.MangledName()),
|
CustomTypeSyntax type => new NubCustomType(type.MangledName()),
|
||||||
FuncTypeSyntax type => new NubFuncType(type.Parameters.Select(BindType).ToList(), BindType(type.ReturnType)),
|
FuncTypeSyntax type => new NubFuncType(type.Parameters.Select(BindType).ToList(), BindType(type.ReturnType)),
|
||||||
PointerTypeSyntax type => new NubPointerType(BindType(type.BaseType)),
|
PointerTypeSyntax type => new NubPointerType(BindType(type.BaseType)),
|
||||||
PrimitiveTypeSyntax type => new NubPrimitiveType(type.SyntaxKind switch
|
PrimitiveTypeSyntax type => new NubPrimitiveType(type.SyntaxKind switch
|
||||||
|
|||||||
@@ -11,25 +11,25 @@ public class DefinitionTable
|
|||||||
_definitions = syntaxTrees.SelectMany(x => x.Definitions).ToList();
|
_definitions = syntaxTrees.SelectMany(x => x.Definitions).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<LocalFuncSyntax> LookupLocalFunc(string @namespace, string name)
|
public IEnumerable<LocalFuncSyntax> LookupLocalFunc(string name)
|
||||||
{
|
{
|
||||||
return _definitions
|
return _definitions
|
||||||
.OfType<LocalFuncSyntax>()
|
.OfType<LocalFuncSyntax>()
|
||||||
.Where(x => x.Namespace == @namespace && x.Name == name);
|
.Where(x => x.Name == name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<ExternFuncSyntax> LookupExternFunc(string @namespace, string name)
|
public IEnumerable<ExternFuncSyntax> LookupExternFunc(string name)
|
||||||
{
|
{
|
||||||
return _definitions
|
return _definitions
|
||||||
.OfType<ExternFuncSyntax>()
|
.OfType<ExternFuncSyntax>()
|
||||||
.Where(x => x.Namespace == @namespace && x.Name == name);
|
.Where(x => x.Name == name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<StructSyntax> LookupStruct(NubCustomType type)
|
public IEnumerable<StructSyntax> LookupStruct(NubCustomType type)
|
||||||
{
|
{
|
||||||
return _definitions
|
return _definitions
|
||||||
.OfType<StructSyntax>()
|
.OfType<StructSyntax>()
|
||||||
.Where(x => x.Namespace == type.Namespace && x.Name == type.Name);
|
.Where(x => x.Name == type.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<StructFieldSyntax> LookupStructField(StructSyntax structNode, string field)
|
public IEnumerable<StructFieldSyntax> LookupStructField(StructSyntax structNode, string field)
|
||||||
@@ -37,20 +37,11 @@ public class DefinitionTable
|
|||||||
return structNode.Fields.Where(x => x.Name == field);
|
return structNode.Fields.Where(x => x.Name == field);
|
||||||
}
|
}
|
||||||
|
|
||||||
// public IEnumerable<TraitFuncImplSyntax> LookupTraitFuncImpl(NubType forType, string name)
|
|
||||||
// {
|
|
||||||
// return _definitions
|
|
||||||
// .OfType<TraitImplSyntax>()
|
|
||||||
// .Where(x => x.ForType == forType)
|
|
||||||
// .SelectMany(x => x.Functions)
|
|
||||||
// .Where(x => x.Name == name);
|
|
||||||
// }
|
|
||||||
|
|
||||||
public IEnumerable<InterfaceSyntax> LookupTrait(NubCustomType type)
|
public IEnumerable<InterfaceSyntax> LookupTrait(NubCustomType type)
|
||||||
{
|
{
|
||||||
return _definitions
|
return _definitions
|
||||||
.OfType<InterfaceSyntax>()
|
.OfType<InterfaceSyntax>()
|
||||||
.Where(x => x.Namespace == type.Namespace && x.Name == type.Name);
|
.Where(x => x.Name == type.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<InterfaceFuncSyntax> LookupTraitFunc(InterfaceSyntax @interface, string name)
|
public IEnumerable<InterfaceFuncSyntax> LookupTraitFunc(InterfaceSyntax @interface, string name)
|
||||||
|
|||||||
@@ -2,24 +2,24 @@
|
|||||||
|
|
||||||
namespace NubLang.Syntax.Binding.Node;
|
namespace NubLang.Syntax.Binding.Node;
|
||||||
|
|
||||||
public abstract record BoundDefinition(string Namespace) : BoundNode;
|
public abstract record BoundDefinition : BoundNode;
|
||||||
|
|
||||||
public record BoundFuncParameter(string Name, NubType Type) : BoundNode;
|
public record BoundFuncParameter(string Name, NubType Type) : BoundNode;
|
||||||
|
|
||||||
public record BoundFuncSignature(IReadOnlyList<BoundFuncParameter> Parameters, NubType ReturnType) : BoundNode;
|
public record BoundFuncSignature(IReadOnlyList<BoundFuncParameter> Parameters, NubType ReturnType) : BoundNode;
|
||||||
|
|
||||||
public record BoundLocalFunc(string Namespace, string Name, BoundFuncSignature Signature, BoundBlock Body) : BoundDefinition(Namespace);
|
public record BoundLocalFunc(string Name, BoundFuncSignature Signature, BoundBlock Body) : BoundDefinition;
|
||||||
|
|
||||||
public record BoundExternFunc(string Namespace, string Name, string CallName, BoundFuncSignature Signature) : BoundDefinition(Namespace);
|
public record BoundExternFunc(string Name, string CallName, BoundFuncSignature Signature) : BoundDefinition;
|
||||||
|
|
||||||
public record BoundStructField(int Index, string Name, NubType Type, Optional<BoundExpression> Value) : BoundNode;
|
public record BoundStructField(int Index, string Name, NubType Type, Optional<BoundExpression> Value) : BoundNode;
|
||||||
|
|
||||||
public record BoundStruct(string Namespace, string Name, IReadOnlyList<BoundStructField> Fields) : BoundDefinition(Namespace);
|
public record BoundStruct(string Name, IReadOnlyList<BoundStructField> Fields) : BoundDefinition;
|
||||||
|
|
||||||
public record BoundTraitFunc(string Name, BoundFuncSignature Signature) : BoundNode;
|
public record BoundTraitFunc(string Name, BoundFuncSignature Signature) : BoundNode;
|
||||||
|
|
||||||
public record BoundTrait(string Namespace, string Name, IReadOnlyList<BoundTraitFunc> Functions) : BoundDefinition(Namespace);
|
public record BoundTrait(string Name, IReadOnlyList<BoundTraitFunc> Functions) : BoundDefinition;
|
||||||
|
|
||||||
public record BoundTraitFuncImpl(string Name, BoundFuncSignature Signature, BoundBlock Body) : BoundNode;
|
public record BoundTraitFuncImpl(string Name, BoundFuncSignature Signature, BoundBlock Body) : BoundNode;
|
||||||
|
|
||||||
public record BoundTraitImpl(string Namespace, NubType TraitType, NubType ForType, IReadOnlyList<BoundTraitFuncImpl> Functions) : BoundDefinition(Namespace);
|
public record BoundTraitImpl(NubType TraitType, NubType ForType, IReadOnlyList<BoundTraitFuncImpl> Functions) : BoundDefinition;
|
||||||
@@ -32,9 +32,9 @@ public record BoundFuncCall(NubType Type, BoundExpression Expression, IReadOnlyL
|
|||||||
|
|
||||||
public record BoundVariableIdent(NubType Type, string Name) : BoundExpression(Type);
|
public record BoundVariableIdent(NubType Type, string Name) : BoundExpression(Type);
|
||||||
|
|
||||||
public record BoundLocalFuncIdent(NubType Type, string Namespace, string Name) : BoundExpression(Type);
|
public record BoundLocalFuncIdent(NubType Type, string Name) : BoundExpression(Type);
|
||||||
|
|
||||||
public record BoundExternFuncIdent(NubType Type, string Namespace, string Name) : BoundExpression(Type);
|
public record BoundExternFuncIdent(NubType Type, string Name) : BoundExpression(Type);
|
||||||
|
|
||||||
public record BoundArrayInitializer(NubType Type, BoundExpression Capacity, NubType ElementType) : BoundExpression(Type);
|
public record BoundArrayInitializer(NubType Type, BoundExpression Capacity, NubType ElementType) : BoundExpression(Type);
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace NubLang.Syntax.Binding.Node;
|
namespace NubLang.Syntax.Binding.Node;
|
||||||
|
|
||||||
public record BoundSyntaxTree(string Namespace, IReadOnlyList<BoundDefinition> Definitions, IReadOnlyList<Diagnostic> Diagnostics);
|
public record BoundSyntaxTree(IReadOnlyList<BoundDefinition> Definitions, IReadOnlyList<Diagnostic> Diagnostics);
|
||||||
|
|
||||||
public abstract record BoundNode;
|
public abstract record BoundNode;
|
||||||
|
|
||||||
|
|||||||
@@ -226,21 +226,20 @@ public class NubStringType : NubComplexType
|
|||||||
public override int GetHashCode() => HashCode.Combine(typeof(NubStringType));
|
public override int GetHashCode() => HashCode.Combine(typeof(NubStringType));
|
||||||
}
|
}
|
||||||
|
|
||||||
public class NubCustomType(string @namespace, string name) : NubComplexType
|
public class NubCustomType(string name) : NubComplexType
|
||||||
{
|
{
|
||||||
public string Namespace { get; } = @namespace;
|
|
||||||
public string Name { get; } = name;
|
public string Name { get; } = name;
|
||||||
|
|
||||||
public CustomTypeKind Kind(BoundDefinitionTable definitionTable)
|
public CustomTypeKind Kind(BoundDefinitionTable definitionTable)
|
||||||
{
|
{
|
||||||
if (definitionTable.GetStructs().Any(x => x.Namespace == Namespace && x.Name == Name))
|
if (definitionTable.GetStructs().Any(x => x.Name == Name))
|
||||||
{
|
{
|
||||||
return CustomTypeKind.Struct;
|
return CustomTypeKind.Struct;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (definitionTable.GetTraits().Any(x => x.Namespace == Namespace && x.Name == Name))
|
if (definitionTable.GetTraits().Any(x => x.Name == Name))
|
||||||
{
|
{
|
||||||
return CustomTypeKind.Trait;
|
return CustomTypeKind.Interface;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new ArgumentException($"Definition table does not have any type information for {this}");
|
throw new ArgumentException($"Definition table does not have any type information for {this}");
|
||||||
@@ -252,7 +251,7 @@ public class NubCustomType(string @namespace, string name) : NubComplexType
|
|||||||
{
|
{
|
||||||
case CustomTypeKind.Struct:
|
case CustomTypeKind.Struct:
|
||||||
{
|
{
|
||||||
var structDef = definitionTable.LookupStruct(Namespace, Name);
|
var structDef = definitionTable.LookupStruct(Name);
|
||||||
var size = 0;
|
var size = 0;
|
||||||
var maxAlignment = 1;
|
var maxAlignment = 1;
|
||||||
|
|
||||||
@@ -267,7 +266,7 @@ public class NubCustomType(string @namespace, string name) : NubComplexType
|
|||||||
|
|
||||||
return AlignTo(size, maxAlignment);
|
return AlignTo(size, maxAlignment);
|
||||||
}
|
}
|
||||||
case CustomTypeKind.Trait:
|
case CustomTypeKind.Interface:
|
||||||
{
|
{
|
||||||
return 16;
|
return 16;
|
||||||
}
|
}
|
||||||
@@ -281,23 +280,23 @@ public class NubCustomType(string @namespace, string name) : NubComplexType
|
|||||||
switch (Kind(definitionTable))
|
switch (Kind(definitionTable))
|
||||||
{
|
{
|
||||||
case CustomTypeKind.Struct:
|
case CustomTypeKind.Struct:
|
||||||
return definitionTable.LookupStruct(Namespace, Name).Fields.Max(f => f.Type.Alignment(definitionTable));
|
return definitionTable.LookupStruct(Name).Fields.Max(f => f.Type.Alignment(definitionTable));
|
||||||
case CustomTypeKind.Trait:
|
case CustomTypeKind.Interface:
|
||||||
return 8;
|
return 8;
|
||||||
default:
|
default:
|
||||||
throw new ArgumentOutOfRangeException();
|
throw new ArgumentOutOfRangeException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString() => $"{Namespace}::{Name}";
|
public override string ToString() => Name;
|
||||||
public override bool Equals(NubType? other) => other is NubCustomType custom && Namespace == custom.Namespace && Name == custom.Name;
|
public override bool Equals(NubType? other) => other is NubCustomType custom && Name == custom.Name;
|
||||||
public override int GetHashCode() => HashCode.Combine(typeof(NubCustomType), Namespace, Name);
|
public override int GetHashCode() => HashCode.Combine(typeof(NubCustomType), Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum CustomTypeKind
|
public enum CustomTypeKind
|
||||||
{
|
{
|
||||||
Struct,
|
Struct,
|
||||||
Trait
|
Interface
|
||||||
}
|
}
|
||||||
|
|
||||||
public class NubArrayType(NubType elementType) : NubComplexType
|
public class NubArrayType(NubType elementType) : NubComplexType
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ using NubLang.Common;
|
|||||||
|
|
||||||
namespace NubLang.Syntax.Parsing.Node;
|
namespace NubLang.Syntax.Parsing.Node;
|
||||||
|
|
||||||
public abstract record DefinitionSyntax(string Namespace) : SyntaxNode;
|
public abstract record DefinitionSyntax : SyntaxNode;
|
||||||
|
|
||||||
public record FuncParameterSyntax(string Name, TypeSyntax Type) : SyntaxNode
|
public record FuncParameterSyntax(string Name, TypeSyntax Type) : SyntaxNode
|
||||||
{
|
{
|
||||||
@@ -25,7 +25,7 @@ public record FuncSignatureSyntax(IReadOnlyList<FuncParameterSyntax> Parameters,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public record LocalFuncSyntax(string Namespace, string Name, FuncSignatureSyntax Signature, BlockSyntax Body) : DefinitionSyntax(Namespace)
|
public record LocalFuncSyntax(string Name, FuncSignatureSyntax Signature, BlockSyntax Body) : DefinitionSyntax
|
||||||
{
|
{
|
||||||
public override IEnumerable<SyntaxNode> GetChildren()
|
public override IEnumerable<SyntaxNode> GetChildren()
|
||||||
{
|
{
|
||||||
@@ -34,7 +34,7 @@ public record LocalFuncSyntax(string Namespace, string Name, FuncSignatureSyntax
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public record ExternFuncSyntax(string Namespace, string Name, string CallName, FuncSignatureSyntax Signature) : DefinitionSyntax(Namespace)
|
public record ExternFuncSyntax(string Name, string CallName, FuncSignatureSyntax Signature) : DefinitionSyntax
|
||||||
{
|
{
|
||||||
public override IEnumerable<SyntaxNode> GetChildren()
|
public override IEnumerable<SyntaxNode> GetChildren()
|
||||||
{
|
{
|
||||||
@@ -63,7 +63,7 @@ public record StructFuncSyntax(string Name, FuncSignatureSyntax Signature, Block
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public record StructSyntax(string Namespace, string Name, IReadOnlyList<StructFieldSyntax> Fields, IReadOnlyList<StructFuncSyntax> Functions) : DefinitionSyntax(Namespace)
|
public record StructSyntax(string Name, IReadOnlyList<StructFieldSyntax> Fields, IReadOnlyList<StructFuncSyntax> Functions) : DefinitionSyntax
|
||||||
{
|
{
|
||||||
public override IEnumerable<SyntaxNode> GetChildren()
|
public override IEnumerable<SyntaxNode> GetChildren()
|
||||||
{
|
{
|
||||||
@@ -87,7 +87,7 @@ public record InterfaceFuncSyntax(string Name, FuncSignatureSyntax Signature) :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public record InterfaceSyntax(string Namespace, string Name, IReadOnlyList<InterfaceFuncSyntax> Functions) : DefinitionSyntax(Namespace)
|
public record InterfaceSyntax(string Name, IReadOnlyList<InterfaceFuncSyntax> Functions) : DefinitionSyntax
|
||||||
{
|
{
|
||||||
public override IEnumerable<SyntaxNode> GetChildren()
|
public override IEnumerable<SyntaxNode> GetChildren()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ public record FuncCallSyntax(ExpressionSyntax Expression, IReadOnlyList<Expressi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public record IdentifierSyntax(Optional<string> Namespace, string Name) : ExpressionSyntax
|
public record IdentifierSyntax(string Name) : ExpressionSyntax
|
||||||
{
|
{
|
||||||
public override IEnumerable<SyntaxNode> GetChildren() => [];
|
public override IEnumerable<SyntaxNode> GetChildren() => [];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ public abstract record SyntaxNode
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public record SyntaxTree(string Namespace, IReadOnlyList<DefinitionSyntax> Definitions) : SyntaxNode
|
public record SyntaxTree(IReadOnlyList<DefinitionSyntax> Definitions) : SyntaxNode
|
||||||
{
|
{
|
||||||
public override IEnumerable<SyntaxNode> GetChildren()
|
public override IEnumerable<SyntaxNode> GetChildren()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ public abstract record TypeSyntax : SyntaxNode
|
|||||||
StringTypeSyntax => "string",
|
StringTypeSyntax => "string",
|
||||||
PointerTypeSyntax ptr => $"ptr_{ptr.BaseType.MangledName()}",
|
PointerTypeSyntax ptr => $"ptr_{ptr.BaseType.MangledName()}",
|
||||||
ArrayTypeSyntax arr => $"arr_{arr.BaseType.MangledName()}",
|
ArrayTypeSyntax arr => $"arr_{arr.BaseType.MangledName()}",
|
||||||
CustomTypeSyntax custom => $"{custom.Namespace}_{custom.Name}",
|
CustomTypeSyntax custom => $"custom_{custom.Name}",
|
||||||
FuncTypeSyntax func => $"func_{string.Join("_", func.Parameters.Select(x => x.MangledName()))}_to_{func.ReturnType.MangledName()}",
|
FuncTypeSyntax func => $"func_{string.Join("_", func.Parameters.Select(x => x.MangledName()))}_to_{func.ReturnType.MangledName()}",
|
||||||
_ => throw new NotSupportedException($"Unknown type syntax: {GetType().Name}")
|
_ => throw new NotSupportedException($"Unknown type syntax: {GetType().Name}")
|
||||||
};
|
};
|
||||||
@@ -75,7 +75,7 @@ public record StringTypeSyntax : TypeSyntax
|
|||||||
public override IEnumerable<SyntaxNode> GetChildren() => [];
|
public override IEnumerable<SyntaxNode> GetChildren() => [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public record CustomTypeSyntax(string Namespace, string Name) : TypeSyntax
|
public record CustomTypeSyntax(string Name) : TypeSyntax
|
||||||
{
|
{
|
||||||
public override IEnumerable<SyntaxNode> GetChildren() => [];
|
public override IEnumerable<SyntaxNode> GetChildren() => [];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,27 +8,21 @@ namespace NubLang.Syntax.Parsing;
|
|||||||
|
|
||||||
public sealed class Parser
|
public sealed class Parser
|
||||||
{
|
{
|
||||||
private string _namespace;
|
private IEnumerable<Token> _tokens = null!;
|
||||||
private readonly IReadOnlyList<Token> _tokens;
|
|
||||||
|
|
||||||
private List<Diagnostic> _diagnostics = [];
|
private readonly List<Diagnostic> _diagnostics = [];
|
||||||
private int _tokenIndex;
|
private int _tokenIndex;
|
||||||
|
|
||||||
public Parser(IReadOnlyList<Token> tokens)
|
public IReadOnlyList<Diagnostic> GetDiagnostics()
|
||||||
{
|
{
|
||||||
_namespace = "default";
|
return _diagnostics;
|
||||||
_tokens = tokens;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public SyntaxTree Parse(out IReadOnlyList<Diagnostic> diagnostics)
|
public SyntaxTree Parse(IEnumerable<Token> tokens)
|
||||||
{
|
{
|
||||||
_diagnostics = [];
|
_diagnostics.Clear();
|
||||||
_tokenIndex = 0;
|
_tokenIndex = 0;
|
||||||
|
_tokens = tokens;
|
||||||
if (TryExpectSymbol(Symbol.Namespace))
|
|
||||||
{
|
|
||||||
_namespace = ExpectIdentifier().Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
var definitions = new List<DefinitionSyntax>();
|
var definitions = new List<DefinitionSyntax>();
|
||||||
|
|
||||||
@@ -68,8 +62,7 @@ public sealed class Parser
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
diagnostics = _diagnostics;
|
return new SyntaxTree(definitions);
|
||||||
return new SyntaxTree(_namespace, definitions);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private FuncSignatureSyntax ParseFuncSignature(FuncParameterSyntax? thisArg = null)
|
private FuncSignatureSyntax ParseFuncSignature(FuncParameterSyntax? thisArg = null)
|
||||||
@@ -134,7 +127,7 @@ public sealed class Parser
|
|||||||
|
|
||||||
var signature = ParseFuncSignature();
|
var signature = ParseFuncSignature();
|
||||||
|
|
||||||
return new ExternFuncSyntax(_namespace, name.Value, callName, signature);
|
return new ExternFuncSyntax(name.Value, callName, signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
private LocalFuncSyntax ParseFunc()
|
private LocalFuncSyntax ParseFunc()
|
||||||
@@ -143,7 +136,7 @@ public sealed class Parser
|
|||||||
var signature = ParseFuncSignature();
|
var signature = ParseFuncSignature();
|
||||||
var body = ParseBlock();
|
var body = ParseBlock();
|
||||||
|
|
||||||
return new LocalFuncSyntax(_namespace, name.Value, signature, body);
|
return new LocalFuncSyntax(name.Value, signature, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
private DefinitionSyntax ParseStruct()
|
private DefinitionSyntax ParseStruct()
|
||||||
@@ -162,7 +155,7 @@ public sealed class Parser
|
|||||||
if (TryExpectSymbol(Symbol.Func))
|
if (TryExpectSymbol(Symbol.Func))
|
||||||
{
|
{
|
||||||
var funcName = ExpectIdentifier().Value;
|
var funcName = ExpectIdentifier().Value;
|
||||||
var thisArg = new FuncParameterSyntax("this", new CustomTypeSyntax(_namespace, name.Value));
|
var thisArg = new FuncParameterSyntax("this", new CustomTypeSyntax(name.Value));
|
||||||
var funcSignature = ParseFuncSignature(thisArg);
|
var funcSignature = ParseFuncSignature(thisArg);
|
||||||
var funcBody = ParseBlock();
|
var funcBody = ParseBlock();
|
||||||
|
|
||||||
@@ -185,7 +178,7 @@ public sealed class Parser
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new StructSyntax(_namespace, name.Value, fields, funcs);
|
return new StructSyntax(name.Value, fields, funcs);
|
||||||
}
|
}
|
||||||
|
|
||||||
private InterfaceSyntax ParseInterface()
|
private InterfaceSyntax ParseInterface()
|
||||||
@@ -206,7 +199,7 @@ public sealed class Parser
|
|||||||
functions.Add(new InterfaceFuncSyntax(funcName, signature));
|
functions.Add(new InterfaceFuncSyntax(funcName, signature));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new InterfaceSyntax(_namespace, name.Value, functions);
|
return new InterfaceSyntax(name.Value, functions);
|
||||||
}
|
}
|
||||||
|
|
||||||
private StatementSyntax ParseStatement()
|
private StatementSyntax ParseStatement()
|
||||||
@@ -419,15 +412,7 @@ public sealed class Parser
|
|||||||
}
|
}
|
||||||
case IdentifierToken identifier:
|
case IdentifierToken identifier:
|
||||||
{
|
{
|
||||||
var @namespace = Optional<string>.Empty();
|
expr = new IdentifierSyntax(identifier.Value);
|
||||||
var name = identifier.Value;
|
|
||||||
if (TryExpectSymbol(Symbol.DoubleColon))
|
|
||||||
{
|
|
||||||
@namespace = identifier.Value;
|
|
||||||
name = ExpectIdentifier().Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
expr = new IdentifierSyntax(@namespace, name);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SymbolToken symbolToken:
|
case SymbolToken symbolToken:
|
||||||
@@ -622,19 +607,8 @@ public sealed class Parser
|
|||||||
"f64" => new PrimitiveTypeSyntax(PrimitiveTypeSyntaxKind.F64),
|
"f64" => new PrimitiveTypeSyntax(PrimitiveTypeSyntaxKind.F64),
|
||||||
"f32" => new PrimitiveTypeSyntax(PrimitiveTypeSyntaxKind.F32),
|
"f32" => new PrimitiveTypeSyntax(PrimitiveTypeSyntaxKind.F32),
|
||||||
"bool" => new PrimitiveTypeSyntax(PrimitiveTypeSyntaxKind.Bool),
|
"bool" => new PrimitiveTypeSyntax(PrimitiveTypeSyntaxKind.Bool),
|
||||||
_ => ParseCustomType()
|
_ => new CustomTypeSyntax(name.Value)
|
||||||
};
|
};
|
||||||
|
|
||||||
TypeSyntax ParseCustomType()
|
|
||||||
{
|
|
||||||
var @namespace = _namespace;
|
|
||||||
if (TryExpectSymbol(Symbol.DoubleColon))
|
|
||||||
{
|
|
||||||
@namespace = ExpectIdentifier().Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new CustomTypeSyntax(@namespace, name.Value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TryExpectSymbol(Symbol.Caret))
|
if (TryExpectSymbol(Symbol.Caret))
|
||||||
@@ -672,14 +646,6 @@ public sealed class Parser
|
|||||||
return new ArrayTypeSyntax(baseType);
|
return new ArrayTypeSyntax(baseType);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Peek().TryGetValue(out var peekToken))
|
|
||||||
{
|
|
||||||
throw new ParseException(Diagnostic
|
|
||||||
.Error("Unexpected end of file while parsing type")
|
|
||||||
.WithHelp("Expected a type name")
|
|
||||||
.Build());
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new ParseException(Diagnostic
|
throw new ParseException(Diagnostic
|
||||||
.Error("Invalid type Syntax")
|
.Error("Invalid type Syntax")
|
||||||
.WithHelp("Expected type name, '^' for pointer, or '[]' for array")
|
.WithHelp("Expected type name, '^' for pointer, or '[]' for array")
|
||||||
|
|||||||
@@ -59,8 +59,6 @@ public enum Symbol
|
|||||||
Struct,
|
Struct,
|
||||||
Caret,
|
Caret,
|
||||||
Ampersand,
|
Ampersand,
|
||||||
DoubleColon,
|
|
||||||
Namespace,
|
|
||||||
Let,
|
Let,
|
||||||
Alloc,
|
Alloc,
|
||||||
Calls,
|
Calls,
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using NubLang.Common;
|
using NubLang.Common;
|
||||||
using NubLang.Diagnostics;
|
|
||||||
|
|
||||||
namespace NubLang.Syntax.Tokenization;
|
namespace NubLang.Syntax.Tokenization;
|
||||||
|
|
||||||
@@ -7,7 +6,6 @@ public sealed class Tokenizer
|
|||||||
{
|
{
|
||||||
private static readonly Dictionary<string, Symbol> Keywords = new()
|
private static readonly Dictionary<string, Symbol> Keywords = new()
|
||||||
{
|
{
|
||||||
["namespace"] = Symbol.Namespace,
|
|
||||||
["func"] = Symbol.Func,
|
["func"] = Symbol.Func,
|
||||||
["if"] = Symbol.If,
|
["if"] = Symbol.If,
|
||||||
["else"] = Symbol.Else,
|
["else"] = Symbol.Else,
|
||||||
@@ -30,7 +28,6 @@ public sealed class Tokenizer
|
|||||||
[['!', '=']] = Symbol.NotEqual,
|
[['!', '=']] = Symbol.NotEqual,
|
||||||
[['<', '=']] = Symbol.LessThanOrEqual,
|
[['<', '=']] = Symbol.LessThanOrEqual,
|
||||||
[['>', '=']] = Symbol.GreaterThanOrEqual,
|
[['>', '=']] = Symbol.GreaterThanOrEqual,
|
||||||
[[':', ':']] = Symbol.DoubleColon,
|
|
||||||
[['=', '>']] = Symbol.Arrow,
|
[['=', '>']] = Symbol.Arrow,
|
||||||
[[':']] = Symbol.Colon,
|
[[':']] = Symbol.Colon,
|
||||||
[['(']] = Symbol.OpenParen,
|
[['(']] = Symbol.OpenParen,
|
||||||
@@ -54,6 +51,11 @@ public sealed class Tokenizer
|
|||||||
[[';']] = Symbol.Semi,
|
[[';']] = Symbol.Semi,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private static readonly (char[] Pattern, Symbol Symbol)[] OrderedSymbols = Symbols
|
||||||
|
.OrderByDescending(kvp => kvp.Key.Length)
|
||||||
|
.Select(kvp => (kvp.Key, kvp.Value))
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
private readonly string _sourceText;
|
private readonly string _sourceText;
|
||||||
private int _index;
|
private int _index;
|
||||||
|
|
||||||
@@ -62,150 +64,147 @@ public sealed class Tokenizer
|
|||||||
_sourceText = sourceText;
|
_sourceText = sourceText;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IReadOnlyList<Token> Tokenize(out IReadOnlyList<Diagnostic> diagnostics)
|
public IEnumerable<Token> Tokenize()
|
||||||
{
|
{
|
||||||
_index = 0;
|
_index = 0;
|
||||||
|
|
||||||
List<Token> tokens = [];
|
while (Peek().TryGetValue(out var current))
|
||||||
while (ParseToken().TryGetValue(out var token))
|
|
||||||
{
|
{
|
||||||
tokens.Add(token);
|
if (char.IsWhiteSpace(current))
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Implement diagnostics
|
|
||||||
diagnostics = [];
|
|
||||||
return tokens;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Optional<Token> ParseToken()
|
|
||||||
{
|
|
||||||
var startIndex = _index;
|
|
||||||
|
|
||||||
if (!Peek().TryGetValue(out var current))
|
|
||||||
{
|
|
||||||
return Optional<Token>.Empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Peek().TryGetValue(out var character) && char.IsWhiteSpace(character))
|
|
||||||
{
|
|
||||||
Next();
|
|
||||||
|
|
||||||
return ParseToken();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (current == '/' && Peek(1).TryGetValue(out var nextChar) && nextChar == '/')
|
|
||||||
{
|
|
||||||
Next();
|
|
||||||
Next();
|
|
||||||
|
|
||||||
while (Peek().TryGetValue(out var ch) && ch != '\n')
|
|
||||||
{
|
{
|
||||||
Next();
|
Next();
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ParseToken();
|
if (current == '/' && Peek(1).TryGetValue(out var nextChar) && nextChar == '/')
|
||||||
}
|
|
||||||
|
|
||||||
if (char.IsLetter(current) || current == '_')
|
|
||||||
{
|
|
||||||
var buffer = string.Empty;
|
|
||||||
|
|
||||||
while (Peek().TryGetValue(out var next) && (char.IsLetterOrDigit(next) || next == '_'))
|
|
||||||
{
|
{
|
||||||
buffer += next;
|
while (Peek().TryGetValue(out var ch) && ch != '\n')
|
||||||
Next();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Keywords.TryGetValue(buffer, out var keywordSymbol))
|
|
||||||
{
|
|
||||||
return new SymbolToken(keywordSymbol);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buffer is "true" or "false")
|
|
||||||
{
|
|
||||||
return new LiteralToken(LiteralKind.Bool, buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new IdentifierToken(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (char.IsDigit(current))
|
|
||||||
{
|
|
||||||
var isFloat = false;
|
|
||||||
var buffer = string.Empty;
|
|
||||||
|
|
||||||
while (Peek().TryGetValue(out var next))
|
|
||||||
{
|
|
||||||
if (next == '.')
|
|
||||||
{
|
{
|
||||||
if (isFloat)
|
|
||||||
{
|
|
||||||
throw new Exception("More than one period found in float literal");
|
|
||||||
}
|
|
||||||
|
|
||||||
isFloat = true;
|
|
||||||
buffer += next;
|
|
||||||
Next();
|
Next();
|
||||||
}
|
}
|
||||||
else if (char.IsDigit(next))
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (char.IsLetter(current) || current == '_')
|
||||||
|
{
|
||||||
|
var buffer = string.Empty;
|
||||||
|
|
||||||
|
while (Peek().TryGetValue(out var next) && (char.IsLetterOrDigit(next) || next == '_'))
|
||||||
{
|
{
|
||||||
buffer += next;
|
buffer += next;
|
||||||
Next();
|
Next();
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
if (Keywords.TryGetValue(buffer, out var keywordSymbol))
|
||||||
{
|
{
|
||||||
break;
|
yield return new SymbolToken(keywordSymbol);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (buffer is "true" or "false")
|
||||||
|
{
|
||||||
|
yield return new LiteralToken(LiteralKind.Bool, buffer);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
yield return new IdentifierToken(buffer);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new LiteralToken(isFloat ? LiteralKind.Float : LiteralKind.Integer, buffer);
|
if (char.IsDigit(current))
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var chain in Symbols)
|
|
||||||
{
|
|
||||||
for (var i = 0; i < chain.Key.Length; i++)
|
|
||||||
{
|
{
|
||||||
var c = Peek(i);
|
var isFloat = false;
|
||||||
if (!c.HasValue || c.Value != chain.Key[i]) break;
|
var buffer = string.Empty;
|
||||||
|
|
||||||
if (i == chain.Key.Length - 1)
|
while (Peek().TryGetValue(out var next))
|
||||||
{
|
{
|
||||||
for (var j = 0; j <= i; j++)
|
if (next == '.')
|
||||||
{
|
{
|
||||||
|
if (isFloat)
|
||||||
|
{
|
||||||
|
throw new Exception("More than one period found in float literal");
|
||||||
|
}
|
||||||
|
|
||||||
|
isFloat = true;
|
||||||
|
buffer += next;
|
||||||
Next();
|
Next();
|
||||||
}
|
}
|
||||||
|
else if (char.IsDigit(next))
|
||||||
return new SymbolToken(chain.Value);
|
{
|
||||||
|
buffer += next;
|
||||||
|
Next();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
yield return new LiteralToken(isFloat ? LiteralKind.Float : LiteralKind.Integer, buffer);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (current == '"')
|
if (current == '"')
|
||||||
{
|
|
||||||
Next();
|
|
||||||
var buffer = string.Empty;
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
{
|
||||||
if (!Peek().TryGetValue(out var next))
|
Next();
|
||||||
|
var buffer = string.Empty;
|
||||||
|
|
||||||
|
while (true)
|
||||||
{
|
{
|
||||||
throw new Exception("Unclosed string literal");
|
if (!Peek().TryGetValue(out var next))
|
||||||
|
{
|
||||||
|
throw new Exception("Unclosed string literal");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (next == '"')
|
||||||
|
{
|
||||||
|
Next();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer += next;
|
||||||
|
Next();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (next == '"')
|
yield return new LiteralToken(LiteralKind.String, buffer);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var foundMatch = false;
|
||||||
|
foreach (var (pattern, symbol) in OrderedSymbols)
|
||||||
|
{
|
||||||
|
for (var i = 0; i < pattern.Length; i++)
|
||||||
|
{
|
||||||
|
var c = Peek(i);
|
||||||
|
if (!c.HasValue || c.Value != pattern[i]) break;
|
||||||
|
|
||||||
|
if (i == pattern.Length - 1)
|
||||||
|
{
|
||||||
|
for (var j = 0; j <= i; j++)
|
||||||
|
{
|
||||||
|
Next();
|
||||||
|
}
|
||||||
|
|
||||||
|
yield return new SymbolToken(symbol);
|
||||||
|
foundMatch = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (foundMatch)
|
||||||
{
|
{
|
||||||
Next();
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer += next;
|
|
||||||
Next();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new LiteralToken(LiteralKind.String, buffer);
|
if (foundMatch)
|
||||||
}
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
throw new Exception($"Unknown character {current}");
|
throw new Exception($"Unknown character {current}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Optional<char> Peek(int offset = 0)
|
private Optional<char> Peek(int offset = 0)
|
||||||
@@ -218,14 +217,8 @@ public sealed class Tokenizer
|
|||||||
return Optional<char>.Empty();
|
return Optional<char>.Empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Optional<char> Next()
|
private void Next()
|
||||||
{
|
{
|
||||||
if (_index < _sourceText.Length)
|
|
||||||
{
|
|
||||||
return _sourceText[_index++];
|
|
||||||
}
|
|
||||||
|
|
||||||
_index++;
|
_index++;
|
||||||
return Optional<char>.Empty();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user