Improved types
This commit is contained in:
@@ -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);
|
||||||
|
|||||||
@@ -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 : "")}";
|
|
||||||
}
|
}
|
||||||
@@ -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);
|
||||||
|
|||||||
@@ -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
6
input/core/arrsize.asm
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
global arrsize
|
||||||
|
section .text
|
||||||
|
|
||||||
|
arrsize:
|
||||||
|
mov rax, [rdi]
|
||||||
|
ret
|
||||||
1
input/core/arrsize.nub
Normal file
1
input/core/arrsize.nub
Normal file
@@ -0,0 +1 @@
|
|||||||
|
extern func arrsize(array: Array<Any>): int64;
|
||||||
@@ -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]);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user