...
This commit is contained in:
@@ -1,57 +1,16 @@
|
||||
struct Name
|
||||
template<T> struct Box
|
||||
{
|
||||
first: cstring
|
||||
last: cstring
|
||||
}
|
||||
|
||||
struct Human
|
||||
{
|
||||
name: Name
|
||||
age: i64
|
||||
}
|
||||
|
||||
trait Printable
|
||||
{
|
||||
func print()
|
||||
}
|
||||
|
||||
impl Printable for Human
|
||||
{
|
||||
func print() {
|
||||
c::puts(this.name.first)
|
||||
}
|
||||
value: T
|
||||
}
|
||||
|
||||
func main(args: []cstring): i64
|
||||
{
|
||||
let human = alloc Human
|
||||
let box = alloc Box<cstring>
|
||||
{
|
||||
name = alloc Name {
|
||||
first = "john"
|
||||
last = "doe"
|
||||
}
|
||||
age = 23
|
||||
value = "bob"
|
||||
}
|
||||
|
||||
human.print()
|
||||
print_result(12, func (num) => num == 12)
|
||||
|
||||
let x: cstring = "test"
|
||||
|
||||
let addr = x&
|
||||
|
||||
c::puts(addr^)
|
||||
c::puts(box.value)
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func print_result(num: u64, delegate: func(u64): bool) {
|
||||
if (delegate(num))
|
||||
{
|
||||
c::puts("true")
|
||||
}
|
||||
else
|
||||
{
|
||||
c::puts("false")
|
||||
}
|
||||
}
|
||||
@@ -11,9 +11,4 @@
|
||||
<ProjectReference Include="..\NubLang.Common\NubLang.Common.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Generation\" />
|
||||
<Folder Include="Syntax\" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -34,7 +34,7 @@ public abstract class NubType : IEquatable<NubType>
|
||||
return false;
|
||||
}
|
||||
|
||||
throw new ArgumentException($"Type {this} is not a simple type, not a compex type");
|
||||
throw new ArgumentException($"Type {this} is not a simple type nor a compex type");
|
||||
}
|
||||
|
||||
public abstract int Size(BoundDefinitionTable definitionTable);
|
||||
@@ -225,10 +225,11 @@ public class NubStringType : NubComplexType
|
||||
public override int GetHashCode() => HashCode.Combine(typeof(NubStringType));
|
||||
}
|
||||
|
||||
public class NubCustomType(string @namespace, string name) : NubComplexType
|
||||
public class NubCustomType(string @namespace, string name, IReadOnlyList<NubType> parameters) : NubComplexType
|
||||
{
|
||||
public string Namespace { get; } = @namespace;
|
||||
public string Name { get; } = name;
|
||||
public IReadOnlyList<NubType> Parameters { get; } = parameters;
|
||||
|
||||
public CustomTypeKind Kind(BoundDefinitionTable definitionTable)
|
||||
{
|
||||
@@ -288,9 +289,22 @@ public class NubCustomType(string @namespace, string name) : NubComplexType
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString() => $"{Namespace}::{Name}";
|
||||
public override bool Equals(NubType? other) => other is NubCustomType custom && Namespace == custom.Namespace && Name == custom.Name;
|
||||
public override int GetHashCode() => HashCode.Combine(typeof(NubCustomType), Namespace, Name);
|
||||
public override string ToString() => $"{Namespace}::{Name}{(Parameters.Any() ? $"<{string.Join(",", Parameters)}>" : "")}";
|
||||
public override bool Equals(NubType? other) => other is NubCustomType custom && Namespace == custom.Namespace && Name == custom.Name && Parameters.SequenceEqual(custom.Parameters);
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
var hash = new HashCode();
|
||||
hash.Add(typeof(NubFuncType));
|
||||
hash.Add(Namespace);
|
||||
hash.Add(Name);
|
||||
foreach (var param in Parameters)
|
||||
{
|
||||
hash.Add(param);
|
||||
}
|
||||
|
||||
return hash.ToHashCode();
|
||||
}
|
||||
}
|
||||
|
||||
public enum CustomTypeKind
|
||||
|
||||
@@ -34,7 +34,7 @@ public sealed class Binder
|
||||
{
|
||||
try
|
||||
{
|
||||
definitions.Add(BindTopLevel(definition));
|
||||
definitions.Add(BindDefinition(definition));
|
||||
}
|
||||
catch (BindException e)
|
||||
{
|
||||
@@ -45,15 +45,15 @@ public sealed class Binder
|
||||
return new BoundSyntaxTree(_syntaxTree.Namespace, definitions, diagnostics);
|
||||
}
|
||||
|
||||
private BoundDefinition BindTopLevel(DefinitionSyntax node)
|
||||
private BoundDefinition BindDefinition(DefinitionSyntax node)
|
||||
{
|
||||
return node switch
|
||||
{
|
||||
ExternFuncSyntax topLevel => BindExternFuncDefinition(topLevel),
|
||||
TraitImplSyntax topLevel => BindTraitImplementation(topLevel),
|
||||
TraitSyntax topLevel => BindTraitDefinition(topLevel),
|
||||
LocalFuncSyntax topLevel => BindLocalFuncDefinition(topLevel),
|
||||
StructSyntax topLevel => BindStruct(topLevel),
|
||||
ExternFuncSyntax definition => BindExternFuncDefinition(definition),
|
||||
TraitImplSyntax definition => BindTraitImplementation(definition),
|
||||
TraitSyntax definition => BindTraitDefinition(definition),
|
||||
LocalFuncSyntax definition => BindLocalFuncDefinition(definition),
|
||||
StructSyntax definition => BindStruct(definition),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(node))
|
||||
};
|
||||
}
|
||||
@@ -403,7 +403,7 @@ public sealed class Binder
|
||||
{
|
||||
if (traits.Length > 1)
|
||||
{
|
||||
throw new BindException(Diagnostic.Error($"Trait {customType.Namespace}::{customType.Name} has multiple definitions").Build());
|
||||
throw new BindException(Diagnostic.Error($"Trait {customType} has multiple definitions").Build());
|
||||
}
|
||||
|
||||
var trait = traits[0];
|
||||
@@ -413,7 +413,7 @@ public sealed class Binder
|
||||
{
|
||||
if (traits.Length > 1)
|
||||
{
|
||||
throw new BindException(Diagnostic.Error($"Trait {trait.Namespace}::{trait.Name} has multiple functions with the name {expression.Member}").Build());
|
||||
throw new BindException(Diagnostic.Error($"Trait {customType} has multiple functions with the name {expression.Member}").Build());
|
||||
}
|
||||
|
||||
var traitFunc = traitFuncs[0];
|
||||
@@ -428,7 +428,7 @@ public sealed class Binder
|
||||
{
|
||||
if (structs.Length > 1)
|
||||
{
|
||||
throw new BindException(Diagnostic.Error($"Struct {customType.Namespace}::{customType.Name} has multiple definitions").Build());
|
||||
throw new BindException(Diagnostic.Error($"Struct {customType} has multiple definitions").Build());
|
||||
}
|
||||
|
||||
var @struct = structs[0];
|
||||
@@ -438,7 +438,7 @@ public sealed class Binder
|
||||
{
|
||||
if (fields.Length > 1)
|
||||
{
|
||||
throw new BindException(Diagnostic.Error($"Struct {@struct.Namespace}::{@struct.Name} has multiple fields with the name {expression.Member}").Build());
|
||||
throw new BindException(Diagnostic.Error($"Struct {customType} has multiple fields with the name {expression.Member}").Build());
|
||||
}
|
||||
|
||||
var field = fields[0];
|
||||
@@ -462,12 +462,12 @@ public sealed class Binder
|
||||
|
||||
if (structs.Length == 0)
|
||||
{
|
||||
throw new BindException(Diagnostic.Error($"Struct {structType.Namespace}::{structType.Name} is not defined").Build());
|
||||
throw new BindException(Diagnostic.Error($"Struct {structType} is not defined").Build());
|
||||
}
|
||||
|
||||
if (structs.Length > 1)
|
||||
{
|
||||
throw new BindException(Diagnostic.Error($"Struct {structType.Namespace}::{structType.Name} has multiple definitions").Build());
|
||||
throw new BindException(Diagnostic.Error($"Struct {structType} has multiple definitions").Build());
|
||||
}
|
||||
|
||||
var @struct = structs[0];
|
||||
@@ -480,18 +480,18 @@ public sealed class Binder
|
||||
|
||||
if (fields.Length == 0)
|
||||
{
|
||||
throw new BindException(Diagnostic.Error($"Struct {@struct.Namespace}::{@struct.Name} does not have a field with the name {field}").Build());
|
||||
throw new BindException(Diagnostic.Error($"Struct {structType} does not have a field with the name {field}").Build());
|
||||
}
|
||||
|
||||
if (fields.Length > 1)
|
||||
{
|
||||
throw new BindException(Diagnostic.Error($"Struct {@struct.Namespace}::{@struct.Name} has multiple fields with the name {field}").Build());
|
||||
throw new BindException(Diagnostic.Error($"Struct {structType} has multiple fields with the name {field}").Build());
|
||||
}
|
||||
|
||||
initializers[field] = BindExpression(initializer, fields[0].Type);
|
||||
}
|
||||
|
||||
return new BoundStructInitializer(expression.Tokens, structType, new NubCustomType(@struct.Namespace, @struct.Name), initializers);
|
||||
return new BoundStructInitializer(expression.Tokens, structType, initializers);
|
||||
}
|
||||
|
||||
private BoundUnaryExpression BindUnaryExpression(UnaryExpressionSyntax expression)
|
||||
|
||||
@@ -52,6 +52,6 @@ public record BoundTraitImplFuncAccess(IReadOnlyList<Token> Tokens, NubType Type
|
||||
|
||||
public record BoundTraitFuncAccess(IReadOnlyList<Token> Tokens, NubType Type, NubCustomType TraitType, BoundExpression Target, string FuncName) : BoundExpression(Tokens, Type);
|
||||
|
||||
public record BoundStructInitializer(IReadOnlyList<Token> Tokens, NubType Type, NubCustomType StructType, Dictionary<string, BoundExpression> Initializers) : BoundExpression(Tokens, Type);
|
||||
public record BoundStructInitializer(IReadOnlyList<Token> Tokens, NubCustomType StructType, Dictionary<string, BoundExpression> Initializers) : BoundExpression(Tokens, StructType);
|
||||
|
||||
public record BoundDereference(IReadOnlyList<Token> Tokens, NubType Type, BoundExpression Expression) : BoundExpression(Tokens, Type);
|
||||
@@ -3,7 +3,7 @@ using NubLang.Syntax.Tokenization;
|
||||
|
||||
namespace NubLang.Syntax.Parsing.Node;
|
||||
|
||||
public record SyntaxTree(string Namespace, IReadOnlyList<DefinitionSyntax> Definitions, IReadOnlyList<Diagnostic> Diagnostics);
|
||||
public record SyntaxTree(string Namespace, IReadOnlyList<DefinitionSyntax> Definitions, IReadOnlyList<TemplateSyntax> Templates, IReadOnlyList<Diagnostic> Diagnostics);
|
||||
|
||||
public abstract record SyntaxNode(IReadOnlyList<Token> Tokens);
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
using NubLang.Syntax.Tokenization;
|
||||
|
||||
namespace NubLang.Syntax.Parsing.Node;
|
||||
|
||||
public abstract record TemplateSyntax(IReadOnlyList<Token> Tokens, string Namespace, IReadOnlyList<string> TemplateParameters) : SyntaxNode(Tokens);
|
||||
|
||||
public record StructTemplateSyntax(IReadOnlyList<Token> Tokens, string Namespace, IReadOnlyList<string> TemplateParameters, StructSyntax Struct) : TemplateSyntax(Tokens, Namespace, TemplateParameters);
|
||||
@@ -30,13 +30,35 @@ public sealed class Parser
|
||||
_namespace = ExpectIdentifier().Value;
|
||||
}
|
||||
|
||||
List<DefinitionSyntax> definitions = [];
|
||||
var definitions = new List<DefinitionSyntax>();
|
||||
var templates = new List<TemplateSyntax>();
|
||||
|
||||
while (Peek().HasValue)
|
||||
{
|
||||
var startIndex = _tokenIndex;
|
||||
|
||||
try
|
||||
{
|
||||
definitions.Add(ParseDefinition());
|
||||
if (TryExpectSymbol(Symbol.Template))
|
||||
{
|
||||
var templateArguments = new List<string>();
|
||||
|
||||
ExpectSymbol(Symbol.LessThan);
|
||||
while (!TryExpectSymbol(Symbol.GreaterThan))
|
||||
{
|
||||
templateArguments.Add(ExpectIdentifier().Value);
|
||||
}
|
||||
|
||||
ExpectSymbol(Symbol.Struct);
|
||||
|
||||
var definition = ParseStruct(_tokenIndex);
|
||||
templates.Add(new StructTemplateSyntax(GetTokens(startIndex), _namespace, templateArguments, definition));
|
||||
}
|
||||
else
|
||||
{
|
||||
var definition = ParseDefinition(startIndex);
|
||||
definitions.Add(definition);
|
||||
}
|
||||
}
|
||||
catch (ParseException ex)
|
||||
{
|
||||
@@ -45,13 +67,11 @@ public sealed class Parser
|
||||
}
|
||||
}
|
||||
|
||||
return new SyntaxTree(_namespace, definitions, _diagnostics);
|
||||
return new SyntaxTree(_namespace, definitions, templates, _diagnostics);
|
||||
}
|
||||
|
||||
private DefinitionSyntax ParseDefinition()
|
||||
private DefinitionSyntax ParseDefinition(int startIndex)
|
||||
{
|
||||
var startIndex = _tokenIndex;
|
||||
|
||||
var keyword = ExpectSymbol();
|
||||
var node = keyword.Symbol switch
|
||||
{
|
||||
@@ -61,8 +81,8 @@ public sealed class Parser
|
||||
Symbol.Trait => ParseTrait(startIndex),
|
||||
Symbol.Impl => ParseImpl(startIndex),
|
||||
_ => throw new ParseException(Diagnostic
|
||||
.Error($"Expected 'func' or 'struct', but found '{keyword.Symbol}'")
|
||||
.WithHelp("Valid definition keywords are 'func' and 'struct'")
|
||||
.Error($"Expected 'extern', 'func', 'struct', 'trait' or 'impl' but found '{keyword.Symbol}'")
|
||||
.WithHelp("Valid definition keywords are 'extern', 'func', 'struct', 'trait' and 'impl'")
|
||||
.At(keyword)
|
||||
.Build())
|
||||
};
|
||||
@@ -660,7 +680,17 @@ public sealed class Parser
|
||||
@namespace = ExpectIdentifier().Value;
|
||||
}
|
||||
|
||||
return new NubCustomType(@namespace, name.Value);
|
||||
var parameters = new List<NubType>();
|
||||
|
||||
if (TryExpectSymbol(Symbol.LessThan))
|
||||
{
|
||||
while (!TryExpectSymbol(Symbol.GreaterThan))
|
||||
{
|
||||
parameters.Add(ParseType());
|
||||
}
|
||||
}
|
||||
|
||||
return new NubCustomType(@namespace, name.Value, parameters);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -803,7 +833,7 @@ public sealed class Parser
|
||||
while (Peek().HasValue)
|
||||
{
|
||||
var token = Peek().Value;
|
||||
if (token is SymbolToken { Symbol: Symbol.Extern or Symbol.Func or Symbol.Struct or Symbol.Trait or Symbol.Impl })
|
||||
if (token is SymbolToken { Symbol: Symbol.Extern or Symbol.Func or Symbol.Struct or Symbol.Trait or Symbol.Impl or Symbol.Template })
|
||||
{
|
||||
break;
|
||||
}
|
||||
@@ -830,7 +860,7 @@ public sealed class Parser
|
||||
|
||||
private List<Token> GetTokens(int startIndex)
|
||||
{
|
||||
return _tokens.Skip(startIndex).Take(Math.Min(_tokenIndex, _tokens.Count() - 1) - startIndex).ToList();
|
||||
return _tokens.Skip(startIndex).Take(Math.Min(_tokenIndex, _tokens.Count - 1) - startIndex).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -73,4 +73,5 @@ public enum Symbol
|
||||
Extern,
|
||||
Semi,
|
||||
Arrow,
|
||||
Template
|
||||
}
|
||||
@@ -22,7 +22,8 @@ public sealed class Tokenizer
|
||||
["trait"] = Symbol.Trait,
|
||||
["impl"] = Symbol.Impl,
|
||||
["for"] = Symbol.For,
|
||||
["extern"] = Symbol.Extern
|
||||
["extern"] = Symbol.Extern,
|
||||
["template"] = Symbol.Template,
|
||||
};
|
||||
|
||||
private static readonly Dictionary<char[], Symbol> Chians = new()
|
||||
|
||||
Reference in New Issue
Block a user