Skip to content

Commit

Permalink
Merge pull request #249 from vein-lang/fixes/generic-adaptation
Browse files Browse the repository at this point in the history
Generic behaviour adaptations
  • Loading branch information
0xF6 authored Jun 26, 2024
2 parents 2d48e14 + 29f248b commit 8f089a6
Show file tree
Hide file tree
Showing 20 changed files with 340 additions and 114 deletions.
6 changes: 4 additions & 2 deletions compiler/compilation/parts/bodies.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,11 @@ public void PostgenerateBody(MethodBuilder method)
// VM needs the end-of-method notation, which is RETURN.
// but in case of the VOID method, user may not write it
// and i didnt think of anything smarter than checking last OpCode
if (!generator._opcodes.Any() && method.ReturnType.TypeCode == TYPE_VOID)
if (!generator._opcodes.Any() && method.ReturnType.IsGeneric)
generator.Emit(OpCodes.RET);
if (generator._opcodes.Any() && generator._opcodes.Last() != OpCodes.RET.Value && method.ReturnType.TypeCode == TYPE_VOID)
if (!generator._opcodes.Any() && !method.ReturnType.IsGeneric && method.ReturnType.Class.TypeCode == TYPE_VOID)
generator.Emit(OpCodes.RET);
if (generator._opcodes.Any() && generator._opcodes.Last() != OpCodes.RET.Value && !method.ReturnType.IsGeneric && method.ReturnType.Class.TypeCode == TYPE_VOID)
generator.Emit(OpCodes.RET);
}

Expand Down
19 changes: 15 additions & 4 deletions compiler/compilation/parts/fields.cs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ private FieldFlags GenerateFieldFlags(MemberDeclarationSyntax member)
if (@override is not null && @override.Args.Any())
{
var exp = @override.Args[0];
if (exp is ArgumentExpression { Value: StringLiteralExpressionSyntax value })
if (exp is { Value: StringLiteralExpressionSyntax value })
name = value.Value;
else
{
Expand Down Expand Up @@ -171,9 +171,20 @@ public void GenerateField((VeinField field, FieldDeclarationSyntax member) t)
// validate type compatible
if (member.Field.Expression is LiteralExpressionSyntax literal)
{
if (field.FieldType.IsGeneric)
{
Log.errors.Enqueue(
$"[red bold]Cannot implicitly convert generic type[/] " +
$"'[purple underline]{literal.GetTypeCode().AsClass()(Types.Storage).Name}[/]' to " +
$"'[purple underline]{field.FieldType.ToTemplateString()}[/]'.\n\t" +
$"at '[orange bold]{literal.Transform.pos.Line} line, {literal.Transform.pos.Column} column[/]' \n\t" +
$"in '[orange bold]{doc.FileEntity}[/]'.");
return;
}

if (literal is NumericLiteralExpressionSyntax numeric)
{
if (!field.FieldType.TypeCode.CanImplicitlyCast(numeric))
if (!field.FieldType.Class.TypeCode.CanImplicitlyCast(numeric))
{
var diff_err = literal.Transform.DiffErrorFull(doc);

Expand All @@ -184,13 +195,13 @@ public void GenerateField((VeinField field, FieldDeclarationSyntax member) t)
Log.errors.Enqueue(
$"[red bold]Cannot implicitly convert type[/] " +
$"'[purple underline]{numeric.GetTypeCode().AsClass()(Types.Storage).Name}[/]' to " +
$"'[purple underline]{field.FieldType.Name}[/]'.\n\t" +
$"'[purple underline]{field.FieldType.ToTemplateString()}[/]'.\n\t" +
$"at '[orange bold]{numeric.Transform.pos.Line} line, {numeric.Transform.pos.Column} column[/]' \n\t" +
$"in '[orange bold]{doc.FileEntity}[/]'." +
$"{diff_err}");
}
}
else if (literal.GetTypeCode() != field.FieldType.TypeCode)
else if (literal.GetTypeCode() != field.FieldType.Class.TypeCode)
{
var diff_err = literal.Transform.DiffErrorFull(doc);
Log.errors.Enqueue(
Expand Down
15 changes: 4 additions & 11 deletions lib/vein.std/std/Out.vein
Original file line number Diff line number Diff line change
@@ -1,17 +1,10 @@
#space "std"


public static class Out
{
[native("__internal__", "@_println")]
public extern static @_println(value: Object): Void;
[native("__internal__", "@_println")]
public extern static @_println(value: i32): Void;

public static print(value: string): Void
|> Out.@_println(value);

public static print(value: i32): Void
|> Out.@_println(value);
}
public extern static _println(value: Object): Void;

public static print<Any>(value: Any): Void
|> Out._println(value);
}
19 changes: 17 additions & 2 deletions lib/vein.std/std/Testable.vein
Original file line number Diff line number Diff line change
@@ -1,16 +1,31 @@
#space "std"


public class Testable
{
public static master(): Void
{
Out.print("yamete...");


aboba(1, "test string");

abobus(delMethod);
}


public static delMethod(i: i32): Void {
Out.print("yamete...");
}

public static aboba<T, E>(t: T, b: E): Void {
Out.print("yamete...");
Out.print(t);
Out.print(b);
}
}

public static abobus(fn: testMethod): Void {
fn(255);
}
}

global alias testMethod(i: i32): Void;
3 changes: 2 additions & 1 deletion runtime/common/exceptions/ConvertNotSupportedException.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ public ConvertNotSupportedException(VeinTypeCode typeCode)
: base($"Cannot get converted, '{typeCode}' is not supported.") { }

public ConvertNotSupportedException(VeinField field)
: base($"Cannot get converted, '{field.FullName}' with '{field.FieldType.FullName.NameWithNS}' type is not supported.") { }
: base(
$"Cannot get converted, '{field.FullName}' with '{field.FieldType.ToTemplateString()}' type is not supported.") { }
}
}
18 changes: 3 additions & 15 deletions runtime/common/reflection/VeinArgumentRef.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ namespace vein.runtime;
#nullable enable
using System;

public class VeinArgumentRef
public class VeinArgumentRef(string name, VeinComplexType complexType)
{
public const string THIS_ARGUMENT = "<this>";

public VeinComplexType ComplexType { get; private set; }
public string Name { get; }
public VeinComplexType ComplexType { get; private set; } = complexType;
public string Name { get; } = name;


public void Temp_ReplaceType(VeinClass @class)
Expand All @@ -23,18 +23,6 @@ public void Temp_ReplaceType(VeinClass @class)

public bool IsGeneric => ComplexType.IsGeneric;

public VeinArgumentRef(string name, VeinClass clazz)
{
Name = name;
ComplexType = clazz;
}

public VeinArgumentRef(string name, VeinTypeArg typeArg)
{
Name = name;
ComplexType = typeArg;
}

public string ToTemplateString() => ComplexType!.ToTemplateString();


Expand Down
184 changes: 176 additions & 8 deletions runtime/common/reflection/VeinClass.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ public class VeinClass : IEquatable<VeinClass>, IAspectable
public List<Aspect> Aspects { get; } = new();
#if DEBUG
public ulong ReferenceID = DebugReference.Get();
protected VeinClass() => CreationPlace = Environment.StackTrace;

#else
protected VeinClass() {}
#endif
public string CreationPlace { get; set; }
internal VeinClass(QualityTypeName name, VeinClass parent, VeinModule module)
Expand All @@ -53,10 +57,7 @@ internal VeinClass(QualityTypeName name, VeinClass[] parents, VeinModule module)
CreationPlace = Environment.StackTrace;
}

protected VeinClass()
{
CreationPlace = Environment.StackTrace;
}


public bool IsSpecial => Flags.HasFlag(ClassFlags.Special);
public bool IsPublic => Flags.HasFlag(ClassFlags.Public);
Expand All @@ -82,7 +83,7 @@ public override string ToString()
=> $"{FullName}, {Flags}";


public VeinMethod FindMethod(string name, IEnumerable<VeinClass> user_types, bool includeThis = false) =>
public VeinMethod FindMethod(string name, IEnumerable<VeinComplexType> user_types, bool includeThis = false) =>
Methods.Concat(Parents.SelectMany(x => x.Methods))
.FirstOrDefault(x =>
{
Expand All @@ -96,13 +97,180 @@ public VeinMethod FindMethod(string name, IEnumerable<VeinClass> user_types, boo
var args = x.Signature.Arguments.Where(z => includeThis || NotThis(z)).Select(z => z.ComplexType).ToList();
var argsHas = CheckCompatibility(userTypes, args);

if (!argsHas && !args.Any(z => z.IsGeneric))
argsHas = CheckInheritance(userTypes.ToArray(), args.Select(z => z.Class).ToArray());
if (!argsHas && !args.Any(z => z.IsGeneric) && !userTypes.Any(z => z.IsGeneric))
argsHas = CheckInheritance(userTypes.Select(z => z.Class).ToArray(), args.Select(z => z.Class).ToArray());

return argsHas;
});

private bool CheckCompatibility(List<VeinClass> userArgs, List<VeinComplexType> methodArgs)

private bool CheckCompatibility(List<VeinComplexType> userArgs, List<VeinComplexType> methodArgs)
{
if (userArgs.Count != methodArgs.Count) return false;

Dictionary<string, VeinClass> t2cMap = new();
Dictionary<string, VeinTypeArg> t2tMap = new();

for (int i = 0; i < userArgs.Count; i++)
{
var userType = userArgs[i];
var methodType = methodArgs[i];

if (methodType.IsGeneric)
{
if (!CheckGenericCompatibility(userType, methodType, t2cMap, t2tMap))
return false;
}
else if (!CheckObjectCompatibility(methodType, userType))
return false;
}
return true;
}

private bool CheckGenericCompatibility(VeinComplexType userType, VeinComplexType methodType, Dictionary<string, VeinClass> genericMap, Dictionary<string, VeinTypeArg> generic2genericMap)
{
var genericName = methodType.TypeArg.Name;

if (userType.IsGeneric)
{
if (generic2genericMap.TryGetValue(genericName, out var val))
return val.Name.Equals(genericName);
generic2genericMap[genericName] = userType.TypeArg;
return true;
}

if (genericMap.TryGetValue(genericName, out var value))
return value.FullName.Equals(userType.Class.FullName);

genericMap[genericName] = userType.Class;
return true;
}

private bool CheckObjectCompatibility(VeinComplexType methodClass, VeinComplexType userClass)
{
if (methodClass.IsGeneric)
return true;
if (methodClass.Class.TypeCode == TYPE_OBJECT && userClass.IsGeneric)
return true;
return false;
}

private bool CheckCompatibilityV4(VeinComplexType[] userArgs, List<VeinComplexType> methodArgs)
{
if (userArgs.Length != methodArgs.Count) return false;

Dictionary<string, VeinClass> genericMap = new();

for (int i = 0; i < userArgs.Length; i++)
{
var userType = userArgs[i];
var methodType = methodArgs[i];

if (methodType.IsGeneric)
{
var genericName = methodType.TypeArg.Name;

if (userType.IsGeneric)
{
if (!methodType.TypeArg.Name.Equals(userType.TypeArg.Name))
return false;
}
else
{
if (genericMap.TryGetValue(genericName, out var value))
{
if (!value.FullName.Equals(userType.Class.FullName) && userType.Class.TypeCode != TYPE_OBJECT)
return false;
}
else
genericMap[genericName] = userType.Class;
}
}
else
{
if (userType.IsGeneric)
return false;
if (!methodType.Class.FullName.Equals(userType.Class.FullName) && methodType.Class.TypeCode != TYPE_OBJECT && userType.Class.TypeCode != TYPE_OBJECT)
return false;
}
}
return true;
}

private bool CheckCompatibilityV3(List<VeinComplexType> userArgs, List<VeinComplexType> methodArgs)
{
if (userArgs.Count != methodArgs.Count) return false;

var genericMap = new Dictionary<string, VeinClass>();

for (int i = 0; i < userArgs.Count; i++)
{
var userType = userArgs[i];
var methodType = methodArgs[i];

if (methodType.IsGeneric)
{
var genericName = methodType.TypeArg.Name;
if (userType.IsGeneric)
{
if (!methodType.TypeArg.Name.Equals(userType.TypeArg.Name))
return false;
}
else
{
if (genericMap.TryGetValue(genericName, out var value))
{
if (!value.FullName.Equals(userType.Class.FullName))
return false;
}
else
genericMap[genericName] = userType.Class;
}
}
else
{
if (userType.IsGeneric)
return false;
if (!methodType.Class.FullName.Equals(userType.Class.FullName))
return false;
}
}
return true;
}


private bool CheckCompatibilityV2(List<VeinComplexType> userArgs, List<VeinComplexType> methodArgs)
{
if (userArgs.Count != methodArgs.Count) return false;

Dictionary<string, VeinClass> genericMap = new();

for (int i = 0; i < userArgs.Count; i++)
{
var userType = userArgs[i];
var methodType = methodArgs[i];

if (methodType.IsGeneric)
{
var genericName = methodType.TypeArg.Name;
if (genericMap.TryGetValue(genericName, out var value))
{
if (!value.FullName.Equals(userType.Class.FullName))
return false;
}
else
genericMap[genericName] = userType.Class;
}
else
{
if (!methodType.Class.FullName.Equals(userType.Class.FullName))
return false;
}
}
return true;
}

private bool CheckCompatibilityV1(List<VeinClass> userArgs, List<VeinComplexType> methodArgs)
{
if (userArgs.Count != methodArgs.Count) return false;

Expand Down
Loading

0 comments on commit 8f089a6

Please sign in to comment.