From 1f4b2a42ebb55da236cb74e394e71503701c6e7f Mon Sep 17 00:00:00 2001 From: nub31 Date: Thu, 30 Jan 2025 17:36:44 +0100 Subject: [PATCH] Improved types --- Nub.Lang/Nub.Lang/Backend/Custom/Generator.cs | 14 ++-- .../Nub.Lang/Backend/Custom/SymbolTable.cs | 16 ++-- Nub.Lang/Nub.Lang/Frontend/Parsing/Parser.cs | 21 +---- Nub.Lang/Nub.Lang/Type.cs | 81 ++++++++++++++----- input/core/arrsize.asm | 6 ++ input/core/arrsize.nub | 1 + input/program.nub | 6 +- output/build.sh | 3 +- 8 files changed, 94 insertions(+), 54 deletions(-) create mode 100644 input/core/arrsize.asm create mode 100644 input/core/arrsize.nub diff --git a/Nub.Lang/Nub.Lang/Backend/Custom/Generator.cs b/Nub.Lang/Nub.Lang/Backend/Custom/Generator.cs index 7f7e342..7e9d77c 100644 --- a/Nub.Lang/Nub.Lang/Backend/Custom/Generator.cs +++ b/Nub.Lang/Nub.Lang/Backend/Custom/Generator.cs @@ -70,6 +70,7 @@ public class Generator } _builder.AppendLine(""" + array_out_of_bounds: mov rax, 60 mov rdi, 69 @@ -358,7 +359,6 @@ public class Generator mov r8, -1 mov r9, 0 syscall - mov QWORD [rax], {arrayInitializer.Length} """); } @@ -424,8 +424,12 @@ public class Generator { switch (type) { - case DelegateType: - throw new NotSupportedException($"Comparison on type {type.GetType().Name} is not supported"); + case AnyType: + throw new InvalidOperationException($"Cannot compare type {type}"); + case ArrayType: + // compare pointers + _builder.AppendLine(" cmp rax, rbx"); + break; case PrimitiveType: _builder.AppendLine(" cmp rax, rbx"); break; @@ -545,10 +549,6 @@ public class Generator { switch (literal.Type) { - case DelegateType: - { - throw new NotImplementedException(); - } case StringType: { var label = _symbolTable.DefineString(literal.Literal); diff --git a/Nub.Lang/Nub.Lang/Backend/Custom/SymbolTable.cs b/Nub.Lang/Nub.Lang/Backend/Custom/SymbolTable.cs index bc018aa..278e1de 100644 --- a/Nub.Lang/Nub.Lang/Backend/Custom/SymbolTable.cs +++ b/Nub.Lang/Nub.Lang/Backend/Custom/SymbolTable.cs @@ -166,10 +166,18 @@ public abstract class Func public bool SignatureMatches(string name, List parameterTypes) { - return Name == name - && Parameters.Count == parameterTypes.Count - && Parameters.Where((p, i) => p.Type == parameterTypes.ElementAt(i)).Count() == parameterTypes.Count; + if (Name != name) return false; + if (Parameters.Count != parameterTypes.Count) return false; + + 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 @@ -217,6 +225,4 @@ public class LocalFunc : Func return localVariable; } - - public override string ToString() => $"{Name}({string.Join(", ", Parameters.Select(p => p.ToString()))}){(ReturnType.HasValue ? ": " + ReturnType.Value : "")}"; } \ No newline at end of file diff --git a/Nub.Lang/Nub.Lang/Frontend/Parsing/Parser.cs b/Nub.Lang/Nub.Lang/Frontend/Parsing/Parser.cs index e9bcec7..f5aa0c6 100644 --- a/Nub.Lang/Nub.Lang/Frontend/Parsing/Parser.cs +++ b/Nub.Lang/Nub.Lang/Frontend/Parsing/Parser.cs @@ -397,23 +397,6 @@ public class Parser switch (name) { - case "Func": - { - List typeArguments = []; - if (TryExpectSymbol(Symbol.LessThan)) - { - while (!TryExpectSymbol(Symbol.GreaterThan)) - { - var type = ParseType(); - typeArguments.Add(type); - TryExpectSymbol(Symbol.Comma); - } - } - - var returnType = Optional.OfNullable(typeArguments.LastOrDefault()); - - return new DelegateType(typeArguments.Take(typeArguments.Count - 1).ToList(), returnType); - } case "String": { return new StringType(); @@ -425,6 +408,10 @@ public class Parser ExpectSymbol(Symbol.GreaterThan); return new ArrayType(innerType); } + case "Any": + { + return new AnyType(); + } default: { return PrimitiveType.Parse(name); diff --git a/Nub.Lang/Nub.Lang/Type.cs b/Nub.Lang/Nub.Lang/Type.cs index 8e0f9ab..da2196e 100644 --- a/Nub.Lang/Nub.Lang/Type.cs +++ b/Nub.Lang/Nub.Lang/Type.cs @@ -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) { 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) { var kind = value switch @@ -26,6 +71,8 @@ public record PrimitiveType : Type 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(); } @@ -36,12 +83,14 @@ public enum PrimitiveTypeKind 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 record ArrayType : Type +public class ArrayType : Type { public ArrayType(Type innerType) { @@ -50,19 +99,13 @@ public record ArrayType : Type public Type InnerType { get; } - public override string ToString() => $"{InnerType}"; -} - -public record DelegateType : Type -{ - public DelegateType(List parameters, Optional returnType) + public override bool IsAssignableTo(Type otherType) { - Parameters = parameters; - ReturnType = returnType; + if (otherType is ArrayType arrayType && arrayType.InnerType.IsAssignableTo(InnerType)) return true; + return base.IsAssignableTo(otherType); } - - public List Parameters { get; } - public Optional 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}>"; } \ No newline at end of file diff --git a/input/core/arrsize.asm b/input/core/arrsize.asm new file mode 100644 index 0000000..6e6056e --- /dev/null +++ b/input/core/arrsize.asm @@ -0,0 +1,6 @@ +global arrsize +section .text + +arrsize: + mov rax, [rdi] + ret \ No newline at end of file diff --git a/input/core/arrsize.nub b/input/core/arrsize.nub new file mode 100644 index 0000000..ef6afdb --- /dev/null +++ b/input/core/arrsize.nub @@ -0,0 +1 @@ +extern func arrsize(array: Array): int64; \ No newline at end of file diff --git a/input/program.nub b/input/program.nub index 5510d45..0337de7 100644 --- a/input/program.nub +++ b/input/program.nub @@ -2,9 +2,5 @@ import "core"; func main() { let x = new Array(2); - x[1] = "test1"; - x[2] = "test2"; - - println(x[1]); - println(x[2]); + println(x == y); } diff --git a/output/build.sh b/output/build.sh index 21e0b40..30c9715 100755 --- a/output/build.sh +++ b/output/build.sh @@ -1,5 +1,6 @@ #!/bin/sh nasm -g -felf64 out.asm -o out.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