Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial Generic Support #247

Merged
merged 22 commits into from
Jun 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading