Improved types

This commit is contained in:
nub31
2025-01-30 17:36:44 +01:00
parent 47b88f58f3
commit 1f4b2a42eb
8 changed files with 94 additions and 54 deletions

View File

@@ -70,6 +70,7 @@ public class Generator
} }
_builder.AppendLine(""" _builder.AppendLine("""
array_out_of_bounds: array_out_of_bounds:
mov rax, 60 mov rax, 60
mov rdi, 69 mov rdi, 69
@@ -358,7 +359,6 @@ public class Generator
mov r8, -1 mov r8, -1
mov r9, 0 mov r9, 0
syscall syscall
mov QWORD [rax], {arrayInitializer.Length} mov QWORD [rax], {arrayInitializer.Length}
"""); """);
} }
@@ -424,8 +424,12 @@ public class Generator
{ {
switch (type) switch (type)
{ {
case DelegateType: case AnyType:
throw new NotSupportedException($"Comparison on type {type.GetType().Name} is not supported"); throw new InvalidOperationException($"Cannot compare type {type}");
case ArrayType:
// compare pointers
_builder.AppendLine(" cmp rax, rbx");
break;
case PrimitiveType: case PrimitiveType:
_builder.AppendLine(" cmp rax, rbx"); _builder.AppendLine(" cmp rax, rbx");
break; break;
@@ -545,10 +549,6 @@ public class Generator
{ {
switch (literal.Type) switch (literal.Type)
{ {
case DelegateType:
{
throw new NotImplementedException();
}
case StringType: case StringType:
{ {
var label = _symbolTable.DefineString(literal.Literal); var label = _symbolTable.DefineString(literal.Literal);

View File

@@ -166,10 +166,18 @@ public abstract class Func
public bool SignatureMatches(string name, List<Type> parameterTypes) public bool SignatureMatches(string name, List<Type> parameterTypes)
{ {
return Name == name if (Name != name) return false;
&& Parameters.Count == parameterTypes.Count if (Parameters.Count != parameterTypes.Count) return false;
&& Parameters.Where((p, i) => p.Type == parameterTypes.ElementAt(i)).Count() == parameterTypes.Count;
for (var i = 0; i < parameterTypes.Count; i++)
{
if (!Parameters[i].Type.IsAssignableTo(parameterTypes[i])) return false;
}
return true;
} }
public override string ToString() => $"{Name}({string.Join(", ", Parameters.Select(p => p.ToString()))}){(ReturnType.HasValue ? ": " + ReturnType.Value : "")}";
} }
public class ExternFunc : Func public class ExternFunc : Func
@@ -217,6 +225,4 @@ public class LocalFunc : Func
return localVariable; return localVariable;
} }
public override string ToString() => $"{Name}({string.Join(", ", Parameters.Select(p => p.ToString()))}){(ReturnType.HasValue ? ": " + ReturnType.Value : "")}";
} }

View File

@@ -397,23 +397,6 @@ public class Parser
switch (name) switch (name)
{ {
case "Func":
{
List<Type> typeArguments = [];
if (TryExpectSymbol(Symbol.LessThan))
{
while (!TryExpectSymbol(Symbol.GreaterThan))
{
var type = ParseType();
typeArguments.Add(type);
TryExpectSymbol(Symbol.Comma);
}
}
var returnType = Optional<Type>.OfNullable(typeArguments.LastOrDefault());
return new DelegateType(typeArguments.Take(typeArguments.Count - 1).ToList(), returnType);
}
case "String": case "String":
{ {
return new StringType(); return new StringType();
@@ -425,6 +408,10 @@ public class Parser
ExpectSymbol(Symbol.GreaterThan); ExpectSymbol(Symbol.GreaterThan);
return new ArrayType(innerType); return new ArrayType(innerType);
} }
case "Any":
{
return new AnyType();
}
default: default:
{ {
return PrimitiveType.Parse(name); return PrimitiveType.Parse(name);

View File

@@ -1,16 +1,61 @@
using Nub.Core; namespace Nub.Lang;
namespace Nub.Lang; public abstract class Type
{
public virtual bool IsAssignableTo(Type otherType)
{
return this == otherType || otherType is AnyType;
}
public override bool Equals(object? obj)
{
if (ReferenceEquals(this, obj)) return true;
if (obj is not Type otherType) return false;
return Equals(otherType);
}
protected abstract bool Equals(Type other);
public abstract override int GetHashCode();
public static bool operator == (Type left, Type right)
{
return ReferenceEquals(left, right) || left.Equals(right);
}
public abstract record Type; public static bool operator !=(Type left, Type right) => !(left == right);
}
public record PrimitiveType : Type public class AnyType : Type
{
protected override bool Equals(Type other) => other is AnyType;
public override int GetHashCode() => nameof(AnyType).GetHashCode();
public override string ToString() => "Any";
}
public class PrimitiveType : Type
{ {
public PrimitiveType(PrimitiveTypeKind kind) public PrimitiveType(PrimitiveTypeKind kind)
{ {
Kind = kind; Kind = kind;
} }
// TODO: This should be looked at more in the future
public override bool IsAssignableTo(Type otherType)
{
if (base.IsAssignableTo(otherType)) return true;
if (otherType is PrimitiveType otherPrimitive)
{
return (Kind, otherPrimitive.Kind) switch
{
(PrimitiveTypeKind.Int32, PrimitiveTypeKind.Int64) => true,
_ => false
};
}
return false;
}
public static PrimitiveType Parse(string value) public static PrimitiveType Parse(string value)
{ {
var kind = value switch var kind = value switch
@@ -26,6 +71,8 @@ public record PrimitiveType : Type
public PrimitiveTypeKind Kind { get; } public PrimitiveTypeKind Kind { get; }
protected override bool Equals(Type other) => other is PrimitiveType primitiveType && Kind == primitiveType.Kind;
public override int GetHashCode() => Kind.GetHashCode();
public override string ToString() => Kind.ToString(); public override string ToString() => Kind.ToString();
} }
@@ -36,12 +83,14 @@ public enum PrimitiveTypeKind
Int32, Int32,
} }
public record StringType : Type public class StringType : Type
{ {
protected override bool Equals(Type other) => other is StringType;
public override int GetHashCode() => nameof(StringType).GetHashCode();
public override string ToString() => "String"; public override string ToString() => "String";
} }
public record ArrayType : Type public class ArrayType : Type
{ {
public ArrayType(Type innerType) public ArrayType(Type innerType)
{ {
@@ -50,19 +99,13 @@ public record ArrayType : Type
public Type InnerType { get; } public Type InnerType { get; }
public override string ToString() => $"{InnerType}"; public override bool IsAssignableTo(Type otherType)
}
public record DelegateType : Type
{
public DelegateType(List<Type> parameters, Optional<Type> returnType)
{ {
Parameters = parameters; if (otherType is ArrayType arrayType && arrayType.InnerType.IsAssignableTo(InnerType)) return true;
ReturnType = returnType; return base.IsAssignableTo(otherType);
} }
public List<Type> Parameters { get; }
public Optional<Type> ReturnType { get; }
public override string ToString() => $"({string.Join(", ", Parameters)}): {(ReturnType.HasValue ? ReturnType.Value.ToString() : "")}"; protected override bool Equals(Type other) => other is ArrayType at && InnerType.Equals(at.InnerType);
public override int GetHashCode() => HashCode.Combine(InnerType);
public override string ToString() => $"Array<{InnerType}>";
} }

6
input/core/arrsize.asm Normal file
View File

@@ -0,0 +1,6 @@
global arrsize
section .text
arrsize:
mov rax, [rdi]
ret

1
input/core/arrsize.nub Normal file
View File

@@ -0,0 +1 @@
extern func arrsize(array: Array<Any>): int64;

View File

@@ -2,9 +2,5 @@ import "core";
func main() { func main() {
let x = new Array<String>(2); let x = new Array<String>(2);
x[1] = "test1"; println(x == y);
x[2] = "test2";
println(x[1]);
println(x[2]);
} }

View File

@@ -1,5 +1,6 @@
#!/bin/sh #!/bin/sh
nasm -g -felf64 out.asm -o out.o nasm -g -felf64 out.asm -o out.o
nasm -g -felf64 ../input/core/strlen.asm -o strlen.o nasm -g -felf64 ../input/core/strlen.asm -o strlen.o
nasm -g -felf64 ../input/core/arrsize.asm -o arrsize.o
ld -o out strlen.o out.o ld -o out strlen.o arrsize.o out.o