Skip to content

Commit

Permalink
Merge pull request #247 from vein-lang/feature/initial-generics
Browse files Browse the repository at this point in the history
Initial Generic Support
  • Loading branch information
0xF6 authored Jun 26, 2024
2 parents 0f911ee + 23cd521 commit 6ab49fa
Show file tree
Hide file tree
Showing 145 changed files with 1,805 additions and 1,099 deletions.
5 changes: 5 additions & 0 deletions compiler/Properties/launchSettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@
"compile vein test 5": {
"commandName": "Project",
"commandLineArgs": "build C:\\git\\std\\asd\\asd.vproj"
},

"compile std library": {
"commandName": "Project",
"commandLineArgs": "build ..\\..\\..\\..\\lib\\vein.std\\std\\std.vproj --ignore-cache"
}
}
}
2 changes: 1 addition & 1 deletion compiler/cmd/NewCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public override int Execute(CommandContext context, NewCommandSettings settings)
curDir.File("app.vein").WriteAllText(
$"""
#space "{name}"
#use "vein/lang"
#use "std"
class App {"{"}
public static master(): void
Expand Down
2 changes: 1 addition & 1 deletion compiler/compilation/CompilationTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ private bool ProcessFiles(IReadOnlyCollection<FileInfo> files, IReadOnlyCollecti
read_task.Increment(1);
try
{
var result = syntax.CompilationUnit.ParseVein(value);
var result = syntax.CompilationUnitV2.ParseVein(value);
result.FileEntity = key;
result.SourceText = value;
// apply root namespace into includes
Expand Down
45 changes: 38 additions & 7 deletions compiler/compilation/parts/args.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,50 @@ private VeinArgumentRef[] GenerateArgument(MethodDeclarationSyntax method, Docum
throw new SkipStatementException();
}

if (!method.Modifiers.Any(x => x.ModificatorKind == ModificatorKind.Static))
if (method.Modifiers.All(x => x.ModificatorKind != ModificatorKind.Static))
args.Add(new VeinArgumentRef(VeinArgumentRef.THIS_ARGUMENT, FetchType(method.OwnerClass.Identifier, doc)));

if (method.Parameters.Count == 0)
return args.ToArray();

return args.Concat(Convert(method.Parameters, method)).ToArray();
}

private IEnumerable<VeinArgumentRef> Convert(List<ParameterSyntax> args, MethodDeclarationSyntax method)
{
VeinClass selector(TypeExpression exp) => FetchType(exp.Typeword, method.OwnerDocument);

return args.Concat(method.Parameters.Select(parameter => new VeinArgumentRef
foreach (var parameter in args)
{
Type = parameter.Type.IsSelf ?
FetchType(method.OwnerClass.Identifier, doc) :
FetchType(parameter.Type, doc),
Name = parameter.Identifier.ExpressionString
var name = parameter.Identifier.ExpressionString;
var generic = method.GenericTypes.FirstOrDefault(x => x.Typeword.Equals(parameter.Type));
var constraints =
method.TypeParameterConstraints.FirstOrDefault(x => x.GenericIndex.Typeword.Equals(parameter.Type));

})).ToArray();
var classGeneric = method.OwnerClass.GenericTypes.FirstOrDefault(x => x.Typeword.Equals(parameter.Type));
var classGenericConstrains = method.OwnerClass.TypeParameterConstraints.FirstOrDefault(x => x.GenericIndex.Typeword.Equals(parameter.Type));

if (generic is not null && classGeneric is not null)
{
Log.Defer.Error($"Detected conflict of declaration generic types, generic type '[red bold]{parameter.Type.Identifier}[/]' " +
$"is declared in the '[red bold]{method.Identifier}[/]' method and in the '[red bold]{method.OwnerClass.Identifier}[/]' class", generic, method.OwnerDocument);
throw new SkipStatementException();
}

if (generic is not null && constraints is not null)
yield return new VeinArgumentRef(name,
generic.Typeword.ToTypeArg([constraints.ToConstraint(selector)]));
else if (generic is not null)
yield return new VeinArgumentRef(name, generic.Typeword.ToTypeArg([]));
else if (classGeneric is not null && classGenericConstrains is not null)
yield return new VeinArgumentRef(name,
classGeneric.Typeword.ToTypeArg([classGenericConstrains.ToConstraint(selector)]));
else if (classGeneric is not null)
yield return new VeinArgumentRef(name, classGeneric.Typeword.ToTypeArg([]));
else if(parameter.Type.IsSelf)
yield return new VeinArgumentRef(name, FetchType(method.OwnerClass.Identifier, method.OwnerDocument));
else
yield return new VeinArgumentRef(name, FetchType(parameter.Type, method.OwnerDocument));
}
}
}
6 changes: 3 additions & 3 deletions compiler/compilation/parts/aspects.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,17 +69,17 @@ public ClassBuilder CompileAspect(AspectDeclarationSyntax member, DocumentDeclar

public void CompileAspectFor(FieldDeclarationSyntax dec, DocumentDeclaration doc, VeinField field) =>
CompileAspectFor(dec.Aspects, x =>
$"aspect/{x.Name}/class/{field.Owner.Name}/field/{dec.Field.Identifier}.",
$"aspect{Aspect.ASPECT_METADATA_DIVIDER}{x.Name}{Aspect.ASPECT_METADATA_DIVIDER}class{Aspect.ASPECT_METADATA_DIVIDER}{field.Owner.Name}{Aspect.ASPECT_METADATA_DIVIDER}field{Aspect.ASPECT_METADATA_DIVIDER}{dec.Field.Identifier}.",
doc, field, AspectTarget.Field);

public void CompileAspectFor(MethodDeclarationSyntax dec, DocumentDeclaration doc, VeinMethod method) =>
CompileAspectFor(dec.Aspects, x =>
$"aspect/{x.Name}/class/{method.Owner.Name}/method/{method.Name}.",
$"aspect{Aspect.ASPECT_METADATA_DIVIDER}{x.Name}{Aspect.ASPECT_METADATA_DIVIDER}class{Aspect.ASPECT_METADATA_DIVIDER}{method.Owner.Name}{Aspect.ASPECT_METADATA_DIVIDER}method{Aspect.ASPECT_METADATA_DIVIDER}{method.Name}.",
doc, method, AspectTarget.Method);

public void CompileAspectFor(ClassDeclarationSyntax dec, DocumentDeclaration doc, VeinClass clazz) =>
CompileAspectFor(dec.Aspects, x =>
$"aspect/{x.Name}/class/{clazz.Name}.", doc, clazz, AspectTarget.Class);
$"aspect{Aspect.ASPECT_METADATA_DIVIDER}{x.Name}{Aspect.ASPECT_METADATA_DIVIDER}class{Aspect.ASPECT_METADATA_DIVIDER}{clazz.Name}.", doc, clazz, AspectTarget.Class);

private void CompileAspectFor(
List<AspectSyntax> aspects,
Expand Down
21 changes: 17 additions & 4 deletions compiler/compilation/parts/classes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,6 @@ private ClassFlags GenerateClassFlags(ClassDeclarationSyntax clazz)
continue;
case { IsNative: true }:
case { IsForwarded: true }:
case { IsAlias: true }:
case { IsAspectUsage: true }:
continue;
//case VeinAnnotationKind.Readonly when !clazz.IsStruct:
Expand Down Expand Up @@ -142,6 +141,11 @@ private ClassFlags GenerateClassFlags(ClassDeclarationSyntax clazz)
public List<(ClassBuilder clazz, MemberDeclarationSyntax member)>
LinkClasses((FileInfo, DocumentDeclaration doc) tuple)
=> LinkClasses(tuple.doc, Types.Storage);

public void GenerateLinksForAliases(DocumentDeclaration doc)
{

}
public List<(ClassBuilder clazz, MemberDeclarationSyntax member)> LinkClasses(DocumentDeclaration doc, VeinCore types)
{
var classes = new List<(ClassBuilder clazz, MemberDeclarationSyntax member)>();
Expand All @@ -167,6 +171,18 @@ private ClassFlags GenerateClassFlags(ClassDeclarationSyntax clazz)
else
Log.Defer.Warn($"[grey]Member[/] [yellow underline]'{member.GetType().Name}'[/] [grey]is not supported.[/]");
}
foreach (var alias in doc.Aliases)
{
if (alias.IsType)
{
var type = FetchType(alias.Type!.Typeword, doc);
Context.Module.alias_table.Add(new VeinAliasType($"{module.Name}%global::{doc.Name}/{alias.AliasName.ExpressionString}",
type));
KnowClasses.Add(alias.AliasName, type);
}
else
Log.Defer.Warn($"Method [grey]Alias[/] [yellow underline]'{alias.AliasName.ExpressionString}'[/] [grey]is not supported.[/]");
}

return classes;
}
Expand All @@ -176,9 +192,6 @@ public ClassBuilder CompileClass(ClassDeclarationSyntax member, DocumentDeclarat
void _defineClass(ClassBuilder clz)
{
KnowClasses.Add(member.Identifier, clz);
if (member.Aspects.FirstOrDefault(x => x.IsAlias)?.Args?.SingleOrDefault().Value is not StringLiteralExpressionSyntax alias)
return;
KnowClasses.Add(new IdentifierExpression(alias.Value), clz);
}


Expand Down
1 change: 0 additions & 1 deletion compiler/compilation/parts/inheritance.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ namespace vein.compilation;
using System.Linq;
using ishtar.emit;
using syntax;
using static runtime.VeinTypeCode;

public partial class CompilationTask
{
Expand Down
9 changes: 8 additions & 1 deletion compiler/compilation/parts/methods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ private MethodFlags GenerateMethodFlags(MethodDeclarationSyntax method)
case "abstract":
flags |= MethodFlags.Virtual;
continue;
case "async":
flags |= MethodFlags.Async;
continue;
default:
Log.Defer.Error(
$"In [orange]'{method.Identifier}'[/] method [red bold]{mod.ModificatorKind}[/] " +
Expand All @@ -96,7 +99,11 @@ private MethodFlags GenerateMethodFlags(MethodDeclarationSyntax method)
$"Modificator [red bold]public[/] cannot be combined with [red bold]private[/] " +
$"in [orange]'{method.Identifier}'[/] method.",
method.ReturnType, method.OwnerClass.OwnerDocument);

if (flags.HasFlag(MethodFlags.Async) && !method.ReturnType.IsAsyncJob)
Log.Defer.Error(
$"Method [orange]'{method.Identifier}'[/] has marked as [red bold]async[/] " +
$"but return type is not [red bold]Job[/] ",
method.ReturnType, method.OwnerClass.OwnerDocument);

return flags;
}
Expand Down
29 changes: 7 additions & 22 deletions compiler/compilation/parts/types.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,41 +4,26 @@ namespace vein.compilation;
using reflection;
using runtime;
using syntax;
using static runtime.VeinTypeCode;

public partial class CompilationTask
{
private void LoadAliases()
{
foreach (var clazz in Target.LoadedModules.SelectMany(x => x.class_table)
.Where(x => x.Aspects.Any(x => x.IsAlias())))
foreach (var alias in Target.LoadedModules.SelectMany(x => x.alias_table).OfType<VeinAliasType>())
{
var aliases = clazz.Aspects.Where(x => x.IsAlias()).Select(x => x.AsAlias());

if (aliases.Count() > 1)
{
Log.Defer.Error($"[red bold]Detected multiple alises[/] '[purple underline]{aliases.Select(x => x.Name)}[/]'");
continue;
}

var alias = aliases.Single();

var class_id = new IdentifierExpression(clazz.Name);
var alias_id = new IdentifierExpression(alias.Name);

var class_id = new IdentifierExpression(alias.type.Name);
var alias_id = new IdentifierExpression(alias.aliasName.Name);

Status.VeinStatus($"Load alias [grey]'{class_id}'[/] -> [grey]'{alias_id}'[/]...");

if (!KnowClasses.ContainsKey(class_id))
KnowClasses[class_id] = clazz;
if (!KnowClasses.ContainsKey(alias_id))
KnowClasses[alias_id] = clazz;
KnowClasses.TryAdd(class_id, alias.type);
KnowClasses.TryAdd(alias_id, alias.type);
}
}
private VeinClass FetchType(IdentifierExpression typename, DocumentDeclaration doc)
{
if (KnowClasses.ContainsKey(typename))
return KnowClasses[typename];
if (KnowClasses.TryGetValue(typename, out var type))
return type;

var retType = module.TryFindType(typename.ExpressionString, doc.Includes);

Expand Down
35 changes: 33 additions & 2 deletions include/ishtar.h
Original file line number Diff line number Diff line change
Expand Up @@ -406,14 +406,14 @@ typedef union {
uint64_t ul;
float f_r4;
double f;
// Note: C does not have a native decimal type
// C does not have a native decimal type
struct {
uint64_t low;
uint64_t mid;
uint64_t high;
uint16_t sign_scale;
} d;
// Note: C does not have a native Half type
// C does not have a native Half type
uint16_t hf;
void* p;
} ishtar_stackval_union_t;
Expand Down Expand Up @@ -533,6 +533,37 @@ typedef struct {
uint64_t vtable_size;
} ishtar_class_t;

typedef struct {
void* mem_base;
void* reg_base;
} ishtar_gc_stack_base;


// ishtar GC
ishtar_stackval_t* ishtar_gc_allocvalue(ishtar_callframe_t* frame);
ishtar_stackval_t* ishtar_gc_allocvalue(ishtar_class_t* clazz, ishtar_callframe_t* frame);
ishtar_stackval_t* ishtar_gc_allocatestack(ishtar_callframe_t* frame, int32_t size);
void ishtar_gc_freestack(ishtar_callframe_t* frame, ishtar_stackval_t* stack, int32_t size);
void ishtar_gc_freevalue(ishtar_stackval_t* value);
void** ishtar_gc_allocvtable(uint32_t size);
ishtar_object_t* ishtar_gc_alloctypeinfoobject(ishtar_class_t* clazz, ishtar_callframe_t* frame);
ishtar_object_t* ishtar_gc_allocfieldinfoobject(void* field, ishtar_callframe_t* frame);
ishtar_object_t* ishtar_gc_allocmethodinfoobject(ishtar_method_t* method, ishtar_callframe_t* frame);
ishtar_object_t* ishtar_gc_allocobject(ishtar_class_t* clazz, ishtar_callframe_t* frame);
void ishtar_gc_freeobject(ishtar_object_t** obj, ishtar_callframe_t* frame);
void ishtar_gc_freeobject(ishtar_object_t* obj, ishtar_callframe_t* frame);
bool ishtar_gc_isalive(ishtar_object_t* obj);
void ishtar_gc_objectregisterfinalizer(ishtar_object_t* obj, void* proc, ishtar_callframe_t* frame);
void ishtar_gc_registerweaklink(ishtar_object_t* obj, void** link, bool longlive);
void ishtar_gc_unregisterweaklink(void** link, bool longlive);
long ishtar_gc_getusedmemorysize();
void ishtar_gc_collect();
void ishtar_gc_register_thread(ishtar_gc_stack_base* attr);
void ishtar_gc_unregister_thread() ;
bool ishtar_gc_get_stack_base(ishtar_gc_stack_base* attr);
// end ishtar GC


#ifdef __cplusplus
}
#endif
Expand Down
35 changes: 30 additions & 5 deletions lib/ast/syntax/Classes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -112,32 +112,57 @@ select ClassDeclarationSyntax.Create(heading, classBody)
.SetStart(heading.Transform.pos)
.SetPos<ClassDeclarationSyntax>(classBody.Transform);

/// example: class Program { void main() {} }

protected internal virtual Parser<ClassDeclarationSyntax> ClassDeclarationBody =>
from @class in
Parse.IgnoreCase("class").Text().Token()
.Or(Parse.IgnoreCase("interface").Text().Token())
.Or(Parse.IgnoreCase("struct").Text().Token()).Commented(this)
from className in IdentifierExpression.Token().Positioned()
from interfaces in Parse.IgnoreCase(":").Token().Then(t => TypeReference.Positioned().DelimitedBy(Parse.Char(',').Token())).Optional()
from generics in GenericsDeclarationParser.Token().Optional()
from interfaces in Parse.IgnoreCase(":").Token()
.Then(_ => TypeReference.Positioned().DelimitedBy(Parse.Char(',').Token())).Optional()
from skippedComments in CommentParser.AnyComment.Token().Many()
from constraints in GenericConstraintParser.Token().Optional()
from openBrace in Parse.Char('{').Token().Commented(this)
from members in ClassMemberDeclaration.Positioned().Token().Many()
from closeBrace in Parse.Char('}').Token().Commented(this)
let classBody = new ClassDeclarationSyntax
{
Identifier = className,
IsInterface = @class.Value == "interface",
IsStruct = @class.Value == "struct",
Inheritances = interfaces.GetOrElse(Enumerable.Empty<TypeSyntax>()).ToList(),
IsInterface = @class.Value == Keywords.INTERFACE,
IsStruct = @class.Value == Keywords.STRUCT,
Inheritances = interfaces.GetOrEmpty().ToList(),
Members = ConvertConstructors(members, className).ToList(),
InnerComments = closeBrace.LeadingComments.ToList(),
TrailingComments = closeBrace.TrailingComments.ToList(),
TypeParameterConstraints = constraints.GetOrEmpty().ToList(),
GenericTypes = generics.GetOrEmpty().ToList()
}
select ClassDeclarationSyntax.Create(null, classBody)
.SetStart(@class.Transform.pos)
.SetEnd(closeBrace.Transform.pos)
.As<ClassDeclarationSyntax>();

protected internal virtual Parser<List<TypeParameterConstraintSyntax>> GenericConstraintParser =>
from keyword in Parse.IgnoreCase("when").Token()
from data in GenericConstraintUnitParser.Positioned().DelimitedBy(Parse.Char(',').Token())
select data.ToList();

protected internal virtual Parser<TypeParameterConstraintSyntax> GenericConstraintUnitParser =>
from genericIndex in TypeExpression.Token().Positioned()
from keyword1 in Parse.IgnoreCase("is").Token()
from constraint in TypeExpression.Token().Positioned()
select new TypeParameterConstraintSyntax(genericIndex, constraint);

protected internal virtual Parser<List<TypeExpression>> GenericsDeclarationParser =>
from openBrace in Parse.Char('<').Token().Commented(this)
from types in TypeExpression.Token().Positioned().DelimitedBy(Parse.Char(','))
from closeBrace in Parse.Char('>').Token().Commented(this)
select types.ToList();




private IEnumerable<MemberDeclarationSyntax> ConvertConstructors(IEnumerable<MemberDeclarationSyntax> members, IdentifierExpression className)
{
Expand Down
1 change: 1 addition & 0 deletions lib/ast/syntax/Expression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,7 @@ from h in Parse.Char('?').Optional()
from h in Parse.Char('*').Optional()
select new PointerSpecifierValue(h.IsDefined);

// type
protected internal virtual Parser<TypeExpression> TypeExpression =>
from type in BaseType.Or(namespace_or_type_name.Token()).Positioned()
from meta in nullable_specifier
Expand Down
11 changes: 11 additions & 0 deletions lib/ast/syntax/Keywords.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace vein.syntax;

public partial class VeinSyntax
{
public static class Keywords
{
public const string INTERFACE = "interface";
public const string CLASS = "class";
public const string STRUCT = "struct";
}
}
Loading

0 comments on commit 6ab49fa

Please sign in to comment.