Primitive to int/float/bool
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
func main(args: []cstring): i64
|
func main(args: []cstring): i64
|
||||||
{
|
{
|
||||||
puts("test" =)
|
puts("test")
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -189,11 +189,11 @@ public partial class QBEGenerator
|
|||||||
|
|
||||||
string sign;
|
string sign;
|
||||||
|
|
||||||
if (simpleType is NubPrimitiveType { Kind: PrimitiveTypeKind.I8 or PrimitiveTypeKind.I16 or PrimitiveTypeKind.I32 or PrimitiveTypeKind.I64 })
|
if (simpleType is NubIntType { Signed: true })
|
||||||
{
|
{
|
||||||
sign = "s";
|
sign = "s";
|
||||||
}
|
}
|
||||||
else if (simpleType is NubPrimitiveType { Kind: PrimitiveTypeKind.U8 or PrimitiveTypeKind.U16 or PrimitiveTypeKind.U32 or PrimitiveTypeKind.U64 })
|
else if (simpleType is NubIntType { Signed: false })
|
||||||
{
|
{
|
||||||
sign = "u";
|
sign = "u";
|
||||||
}
|
}
|
||||||
@@ -245,21 +245,21 @@ public partial class QBEGenerator
|
|||||||
{
|
{
|
||||||
case LiteralKind.Integer:
|
case LiteralKind.Integer:
|
||||||
{
|
{
|
||||||
if (literal.Type is NubPrimitiveType { Kind: PrimitiveTypeKind.F32 })
|
if (literal.Type is NubFloatType { Width: 32 })
|
||||||
{
|
{
|
||||||
var value = float.Parse(literal.Value, CultureInfo.InvariantCulture);
|
var value = float.Parse(literal.Value, CultureInfo.InvariantCulture);
|
||||||
var bits = BitConverter.SingleToInt32Bits(value);
|
var bits = BitConverter.SingleToInt32Bits(value);
|
||||||
return new Val(bits.ToString(), literal.Type, ValKind.Direct);
|
return new Val(bits.ToString(), literal.Type, ValKind.Direct);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (literal.Type is NubPrimitiveType { Kind: PrimitiveTypeKind.F64 })
|
if (literal.Type is NubFloatType { Width: 64 })
|
||||||
{
|
{
|
||||||
var value = double.Parse(literal.Value, CultureInfo.InvariantCulture);
|
var value = double.Parse(literal.Value, CultureInfo.InvariantCulture);
|
||||||
var bits = BitConverter.DoubleToInt64Bits(value);
|
var bits = BitConverter.DoubleToInt64Bits(value);
|
||||||
return new Val(bits.ToString(), literal.Type, ValKind.Direct);
|
return new Val(bits.ToString(), literal.Type, ValKind.Direct);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (literal.Type is NubPrimitiveType { Kind: PrimitiveTypeKind.I8 or PrimitiveTypeKind.U8 or PrimitiveTypeKind.I16 or PrimitiveTypeKind.U16 or PrimitiveTypeKind.I32 or PrimitiveTypeKind.U32 or PrimitiveTypeKind.I64 or PrimitiveTypeKind.U64 })
|
if (literal.Type is NubIntType)
|
||||||
{
|
{
|
||||||
return new Val(literal.Value, literal.Type, ValKind.Direct);
|
return new Val(literal.Value, literal.Type, ValKind.Direct);
|
||||||
}
|
}
|
||||||
@@ -268,19 +268,19 @@ public partial class QBEGenerator
|
|||||||
}
|
}
|
||||||
case LiteralKind.Float:
|
case LiteralKind.Float:
|
||||||
{
|
{
|
||||||
if (literal.Type is NubPrimitiveType { Kind: PrimitiveTypeKind.I8 or PrimitiveTypeKind.U8 or PrimitiveTypeKind.I16 or PrimitiveTypeKind.U16 or PrimitiveTypeKind.I32 or PrimitiveTypeKind.U32 or PrimitiveTypeKind.I64 or PrimitiveTypeKind.U64 })
|
if (literal.Type is NubIntType)
|
||||||
{
|
{
|
||||||
return new Val(literal.Value.Split(".").First(), literal.Type, ValKind.Direct);
|
return new Val(literal.Value.Split(".").First(), literal.Type, ValKind.Direct);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (literal.Type is NubPrimitiveType { Kind: PrimitiveTypeKind.F32 })
|
if (literal.Type is NubFloatType { Width: 32 })
|
||||||
{
|
{
|
||||||
var value = float.Parse(literal.Value, CultureInfo.InvariantCulture);
|
var value = float.Parse(literal.Value, CultureInfo.InvariantCulture);
|
||||||
var bits = BitConverter.SingleToInt32Bits(value);
|
var bits = BitConverter.SingleToInt32Bits(value);
|
||||||
return new Val(bits.ToString(), literal.Type, ValKind.Direct);
|
return new Val(bits.ToString(), literal.Type, ValKind.Direct);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (literal.Type is NubPrimitiveType { Kind: PrimitiveTypeKind.F64 })
|
if (literal.Type is NubFloatType { Width: 64 })
|
||||||
{
|
{
|
||||||
var value = double.Parse(literal.Value, CultureInfo.InvariantCulture);
|
var value = double.Parse(literal.Value, CultureInfo.InvariantCulture);
|
||||||
var bits = BitConverter.DoubleToInt64Bits(value);
|
var bits = BitConverter.DoubleToInt64Bits(value);
|
||||||
@@ -309,7 +309,7 @@ public partial class QBEGenerator
|
|||||||
}
|
}
|
||||||
case LiteralKind.Bool:
|
case LiteralKind.Bool:
|
||||||
{
|
{
|
||||||
if (literal.Type is NubPrimitiveType { Kind: PrimitiveTypeKind.Bool })
|
if (literal.Type is NubBoolType)
|
||||||
{
|
{
|
||||||
return new Val(bool.Parse(literal.Value) ? "1" : "0", literal.Type, ValKind.Direct);
|
return new Val(bool.Parse(literal.Value) ? "1" : "0", literal.Type, ValKind.Direct);
|
||||||
}
|
}
|
||||||
@@ -360,16 +360,16 @@ public partial class QBEGenerator
|
|||||||
{
|
{
|
||||||
switch (unaryExpression.Operand.Type)
|
switch (unaryExpression.Operand.Type)
|
||||||
{
|
{
|
||||||
case NubPrimitiveType { Kind: PrimitiveTypeKind.I64 }:
|
case NubIntType { Signed: true, Width: 64 }:
|
||||||
_writer.Indented($"{outputName} =l neg {operand}");
|
_writer.Indented($"{outputName} =l neg {operand}");
|
||||||
return new Val(outputName, unaryExpression.Type, ValKind.Direct);
|
return new Val(outputName, unaryExpression.Type, ValKind.Direct);
|
||||||
case NubPrimitiveType { Kind: PrimitiveTypeKind.I32 or PrimitiveTypeKind.I16 or PrimitiveTypeKind.I8 }:
|
case NubIntType { Signed: true, Width: 8 or 16 or 32 }:
|
||||||
_writer.Indented($"{outputName} =w neg {operand}");
|
_writer.Indented($"{outputName} =w neg {operand}");
|
||||||
return new Val(outputName, unaryExpression.Type, ValKind.Direct);
|
return new Val(outputName, unaryExpression.Type, ValKind.Direct);
|
||||||
case NubPrimitiveType { Kind: PrimitiveTypeKind.F64 }:
|
case NubFloatType { Width: 64 }:
|
||||||
_writer.Indented($"{outputName} =d neg {operand}");
|
_writer.Indented($"{outputName} =d neg {operand}");
|
||||||
return new Val(outputName, unaryExpression.Type, ValKind.Direct);
|
return new Val(outputName, unaryExpression.Type, ValKind.Direct);
|
||||||
case NubPrimitiveType { Kind: PrimitiveTypeKind.F32 }:
|
case NubFloatType { Width: 32 }:
|
||||||
_writer.Indented($"{outputName} =s neg {operand}");
|
_writer.Indented($"{outputName} =s neg {operand}");
|
||||||
return new Val(outputName, unaryExpression.Type, ValKind.Direct);
|
return new Val(outputName, unaryExpression.Type, ValKind.Direct);
|
||||||
}
|
}
|
||||||
@@ -380,7 +380,7 @@ public partial class QBEGenerator
|
|||||||
{
|
{
|
||||||
switch (unaryExpression.Operand.Type)
|
switch (unaryExpression.Operand.Type)
|
||||||
{
|
{
|
||||||
case NubPrimitiveType { Kind: PrimitiveTypeKind.Bool }:
|
case NubBoolType:
|
||||||
_writer.Indented($"{outputName} =w xor {operand}, 1");
|
_writer.Indented($"{outputName} =w xor {operand}, 1");
|
||||||
return new Val(outputName, unaryExpression.Type, ValKind.Direct);
|
return new Val(outputName, unaryExpression.Type, ValKind.Direct);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -580,22 +580,54 @@ public sealed class Parser
|
|||||||
var startIndex = _tokenIndex;
|
var startIndex = _tokenIndex;
|
||||||
if (TryExpectIdentifier(out var name))
|
if (TryExpectIdentifier(out var name))
|
||||||
{
|
{
|
||||||
|
if (name.Value[0] == 'u' && int.TryParse(name.Value[1..], out var size))
|
||||||
|
{
|
||||||
|
if (size is not 8 and not 16 and not 32 and not 64)
|
||||||
|
{
|
||||||
|
throw new ParseException(Diagnostic
|
||||||
|
.Error("Arbitrary uint size is not supported")
|
||||||
|
.WithHelp("Use u8, u16, u32 or u64")
|
||||||
|
.At(name)
|
||||||
|
.Build());
|
||||||
|
}
|
||||||
|
|
||||||
|
return new IntTypeSyntax(GetTokens(startIndex), false, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name.Value[0] == 'i' && int.TryParse(name.Value[1..], out size))
|
||||||
|
{
|
||||||
|
if (size is not 8 and not 16 and not 32 and not 64)
|
||||||
|
{
|
||||||
|
throw new ParseException(Diagnostic
|
||||||
|
.Error("Arbitrary int size is not supported")
|
||||||
|
.WithHelp("Use i8, i16, i32 or i64")
|
||||||
|
.At(name)
|
||||||
|
.Build());
|
||||||
|
}
|
||||||
|
|
||||||
|
return new IntTypeSyntax(GetTokens(startIndex), true, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name.Value[0] == 'f' && int.TryParse(name.Value[1..], out size))
|
||||||
|
{
|
||||||
|
if (size is not 32 and not 64)
|
||||||
|
{
|
||||||
|
throw new ParseException(Diagnostic
|
||||||
|
.Error("Arbitrary float size is not supported")
|
||||||
|
.WithHelp("Use f32 or f64")
|
||||||
|
.At(name)
|
||||||
|
.Build());
|
||||||
|
}
|
||||||
|
|
||||||
|
return new FloatTypeSyntax(GetTokens(startIndex), size);
|
||||||
|
}
|
||||||
|
|
||||||
return name.Value switch
|
return name.Value switch
|
||||||
{
|
{
|
||||||
"void" => new VoidTypeSyntax(GetTokens(startIndex)),
|
"void" => new VoidTypeSyntax(GetTokens(startIndex)),
|
||||||
"string" => new StringTypeSyntax(GetTokens(startIndex)),
|
"string" => new StringTypeSyntax(GetTokens(startIndex)),
|
||||||
"cstring" => new CStringTypeSyntax(GetTokens(startIndex)),
|
"cstring" => new CStringTypeSyntax(GetTokens(startIndex)),
|
||||||
"i64" => new PrimitiveTypeSyntax(GetTokens(startIndex), PrimitiveTypeSyntaxKind.I64),
|
"bool" => new BoolTypeSyntax(GetTokens(startIndex)),
|
||||||
"i32" => new PrimitiveTypeSyntax(GetTokens(startIndex), PrimitiveTypeSyntaxKind.I32),
|
|
||||||
"i16" => new PrimitiveTypeSyntax(GetTokens(startIndex), PrimitiveTypeSyntaxKind.I16),
|
|
||||||
"i8" => new PrimitiveTypeSyntax(GetTokens(startIndex), PrimitiveTypeSyntaxKind.I8),
|
|
||||||
"u64" => new PrimitiveTypeSyntax(GetTokens(startIndex), PrimitiveTypeSyntaxKind.U64),
|
|
||||||
"u32" => new PrimitiveTypeSyntax(GetTokens(startIndex), PrimitiveTypeSyntaxKind.U32),
|
|
||||||
"u16" => new PrimitiveTypeSyntax(GetTokens(startIndex), PrimitiveTypeSyntaxKind.U16),
|
|
||||||
"u8" => new PrimitiveTypeSyntax(GetTokens(startIndex), PrimitiveTypeSyntaxKind.U8),
|
|
||||||
"f64" => new PrimitiveTypeSyntax(GetTokens(startIndex), PrimitiveTypeSyntaxKind.F64),
|
|
||||||
"f32" => new PrimitiveTypeSyntax(GetTokens(startIndex), PrimitiveTypeSyntaxKind.F32),
|
|
||||||
"bool" => new PrimitiveTypeSyntax(GetTokens(startIndex), PrimitiveTypeSyntaxKind.Bool),
|
|
||||||
_ => new CustomTypeSyntax(GetTokens(startIndex), name.Value)
|
_ => new CustomTypeSyntax(GetTokens(startIndex), name.Value)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,35 +2,22 @@ using NubLang.Tokenization;
|
|||||||
|
|
||||||
namespace NubLang.Parsing.Syntax;
|
namespace NubLang.Parsing.Syntax;
|
||||||
|
|
||||||
public enum PrimitiveTypeSyntaxKind
|
|
||||||
{
|
|
||||||
I64,
|
|
||||||
I32,
|
|
||||||
I16,
|
|
||||||
I8,
|
|
||||||
U64,
|
|
||||||
U32,
|
|
||||||
U16,
|
|
||||||
U8,
|
|
||||||
F64,
|
|
||||||
F32,
|
|
||||||
Bool
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract record TypeSyntax(IEnumerable<Token> Tokens) : SyntaxNode(Tokens)
|
public abstract record TypeSyntax(IEnumerable<Token> Tokens) : SyntaxNode(Tokens)
|
||||||
{
|
{
|
||||||
public string MangledName()
|
public string MangledName()
|
||||||
{
|
{
|
||||||
return this switch
|
return this switch
|
||||||
{
|
{
|
||||||
PrimitiveTypeSyntax primitive => primitive.SyntaxKind.ToString().ToLower(),
|
|
||||||
VoidTypeSyntax => "void",
|
VoidTypeSyntax => "void",
|
||||||
CStringTypeSyntax => "cstring",
|
CStringTypeSyntax => "cstring",
|
||||||
StringTypeSyntax => "string",
|
StringTypeSyntax => "string",
|
||||||
PointerTypeSyntax ptr => $"ptr_{ptr.BaseType.MangledName()}",
|
PointerTypeSyntax ptr => $"ptr_{ptr.BaseType.MangledName()}",
|
||||||
ArrayTypeSyntax arr => $"arr_{arr.BaseType.MangledName()}",
|
ArrayTypeSyntax arr => $"arr_{arr.BaseType.MangledName()}",
|
||||||
|
BoolTypeSyntax => "bool",
|
||||||
CustomTypeSyntax custom => $"custom_{custom.Name}",
|
CustomTypeSyntax custom => $"custom_{custom.Name}",
|
||||||
|
FloatTypeSyntax @float => $"f{@float.Width}",
|
||||||
FuncTypeSyntax func => $"func_{string.Join("_", func.Parameters.Select(x => x.MangledName()))}_to_{func.ReturnType.MangledName()}",
|
FuncTypeSyntax func => $"func_{string.Join("_", func.Parameters.Select(x => x.MangledName()))}_to_{func.ReturnType.MangledName()}",
|
||||||
|
IntTypeSyntax @int => $"{(@int.Signed ? "i" : "u")}{@int.Width}",
|
||||||
_ => throw new NotSupportedException($"Unknown type syntax: {GetType().Name}")
|
_ => throw new NotSupportedException($"Unknown type syntax: {GetType().Name}")
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -62,12 +49,17 @@ public record VoidTypeSyntax(IEnumerable<Token> Tokens) : TypeSyntax(Tokens)
|
|||||||
public override IEnumerable<SyntaxNode> GetChildren() => [];
|
public override IEnumerable<SyntaxNode> GetChildren() => [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public record PrimitiveTypeSyntax(IEnumerable<Token> Tokens, PrimitiveTypeSyntaxKind SyntaxKind) : TypeSyntax(Tokens)
|
public record IntTypeSyntax(IEnumerable<Token> Tokens, bool Signed, int Width) : TypeSyntax(Tokens)
|
||||||
{
|
{
|
||||||
public override IEnumerable<SyntaxNode> GetChildren() => [];
|
public override IEnumerable<SyntaxNode> GetChildren() => [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public record CStringTypeSyntax(IEnumerable<Token> Tokens) : TypeSyntax(Tokens)
|
public record FloatTypeSyntax(IEnumerable<Token> Tokens, int Width) : TypeSyntax(Tokens)
|
||||||
|
{
|
||||||
|
public override IEnumerable<SyntaxNode> GetChildren() => [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public record BoolTypeSyntax(IEnumerable<Token> Tokens) : TypeSyntax(Tokens)
|
||||||
{
|
{
|
||||||
public override IEnumerable<SyntaxNode> GetChildren() => [];
|
public override IEnumerable<SyntaxNode> GetChildren() => [];
|
||||||
}
|
}
|
||||||
@@ -77,7 +69,7 @@ public record StringTypeSyntax(IEnumerable<Token> Tokens) : TypeSyntax(Tokens)
|
|||||||
public override IEnumerable<SyntaxNode> GetChildren() => [];
|
public override IEnumerable<SyntaxNode> GetChildren() => [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public record CustomTypeSyntax(IEnumerable<Token> Tokens, string Name) : TypeSyntax(Tokens)
|
public record CStringTypeSyntax(IEnumerable<Token> Tokens) : TypeSyntax(Tokens)
|
||||||
{
|
{
|
||||||
public override IEnumerable<SyntaxNode> GetChildren() => [];
|
public override IEnumerable<SyntaxNode> GetChildren() => [];
|
||||||
}
|
}
|
||||||
@@ -88,4 +80,9 @@ public record ArrayTypeSyntax(IEnumerable<Token> Tokens, TypeSyntax BaseType) :
|
|||||||
{
|
{
|
||||||
yield return BaseType;
|
yield return BaseType;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public record CustomTypeSyntax(IEnumerable<Token> Tokens, string Name) : TypeSyntax(Tokens)
|
||||||
|
{
|
||||||
|
public override IEnumerable<SyntaxNode> GetChildren() => [];
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using NubLang.Parsing.Syntax;
|
using NubLang.Parsing.Syntax;
|
||||||
|
using NubLang.TypeChecking.Node;
|
||||||
|
|
||||||
namespace NubLang.TypeChecking;
|
namespace NubLang.TypeChecking;
|
||||||
|
|
||||||
|
|||||||
@@ -1,24 +1,10 @@
|
|||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using NubLang.Generation;
|
using NubLang.Generation;
|
||||||
|
|
||||||
namespace NubLang.TypeChecking;
|
namespace NubLang.TypeChecking.Node;
|
||||||
|
|
||||||
public abstract class NubType : IEquatable<NubType>
|
public abstract class NubType : IEquatable<NubType>
|
||||||
{
|
{
|
||||||
public bool IsNumber => this is NubPrimitiveType
|
|
||||||
{
|
|
||||||
Kind: PrimitiveTypeKind.I8
|
|
||||||
or PrimitiveTypeKind.I16
|
|
||||||
or PrimitiveTypeKind.I32
|
|
||||||
or PrimitiveTypeKind.I64
|
|
||||||
or PrimitiveTypeKind.U8
|
|
||||||
or PrimitiveTypeKind.U16
|
|
||||||
or PrimitiveTypeKind.U32
|
|
||||||
or PrimitiveTypeKind.U64
|
|
||||||
or PrimitiveTypeKind.F32
|
|
||||||
or PrimitiveTypeKind.F64
|
|
||||||
};
|
|
||||||
|
|
||||||
public bool IsSimpleType([NotNullWhen(true)] out NubSimpleType? simpleType, [NotNullWhen(false)] out NubComplexType? complexType)
|
public bool IsSimpleType([NotNullWhen(true)] out NubSimpleType? simpleType, [NotNullWhen(false)] out NubComplexType? complexType)
|
||||||
{
|
{
|
||||||
if (this is NubSimpleType st)
|
if (this is NubSimpleType st)
|
||||||
@@ -35,7 +21,7 @@ public abstract class NubType : IEquatable<NubType>
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new ArgumentException($"Type {this} is not a simple type nor a compex type");
|
throw new ArgumentException($"Type {this} is not a simple type nor a complex type");
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract int Size(TypedDefinitionTable definitionTable);
|
public abstract int Size(TypedDefinitionTable definitionTable);
|
||||||
@@ -95,6 +81,61 @@ public abstract class NubSimpleType : NubType
|
|||||||
|
|
||||||
#region Simple types
|
#region Simple types
|
||||||
|
|
||||||
|
public class NubIntType(bool signed, int width) : NubSimpleType
|
||||||
|
{
|
||||||
|
public bool Signed { get; } = signed;
|
||||||
|
public int Width { get; } = width;
|
||||||
|
|
||||||
|
public override StorageSize StorageSize => Signed switch
|
||||||
|
{
|
||||||
|
true => Width switch
|
||||||
|
{
|
||||||
|
8 => StorageSize.I8,
|
||||||
|
16 => StorageSize.I16,
|
||||||
|
32 => StorageSize.I32,
|
||||||
|
64 => StorageSize.I64,
|
||||||
|
_ => throw new ArgumentOutOfRangeException(nameof(Width))
|
||||||
|
},
|
||||||
|
false => Width switch
|
||||||
|
{
|
||||||
|
8 => StorageSize.U8,
|
||||||
|
16 => StorageSize.U16,
|
||||||
|
32 => StorageSize.U32,
|
||||||
|
64 => StorageSize.U64,
|
||||||
|
_ => throw new ArgumentOutOfRangeException(nameof(Width))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public override string ToString() => $"{(Signed ? "i" : "u")}{Width}";
|
||||||
|
public override bool Equals(NubType? other) => other is NubIntType @int && @int.Width == Width && @int.Signed == Signed;
|
||||||
|
public override int GetHashCode() => HashCode.Combine(typeof(NubIntType), Signed, Width);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class NubFloatType(int width) : NubSimpleType
|
||||||
|
{
|
||||||
|
public int Width { get; } = width;
|
||||||
|
|
||||||
|
public override StorageSize StorageSize => Width switch
|
||||||
|
{
|
||||||
|
32 => StorageSize.F32,
|
||||||
|
64 => StorageSize.F64,
|
||||||
|
_ => throw new ArgumentOutOfRangeException(nameof(Width))
|
||||||
|
};
|
||||||
|
|
||||||
|
public override string ToString() => $"f{Width}";
|
||||||
|
public override bool Equals(NubType? other) => other is NubFloatType @int && @int.Width == Width;
|
||||||
|
public override int GetHashCode() => HashCode.Combine(typeof(NubFloatType), Width);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class NubBoolType : NubSimpleType
|
||||||
|
{
|
||||||
|
public override StorageSize StorageSize => StorageSize.U8;
|
||||||
|
|
||||||
|
public override string ToString() => "bool";
|
||||||
|
public override bool Equals(NubType? other) => other is NubBoolType;
|
||||||
|
public override int GetHashCode() => HashCode.Combine(typeof(NubBoolType));
|
||||||
|
}
|
||||||
|
|
||||||
public class NubFuncType(List<NubType> parameters, NubType returnType) : NubSimpleType
|
public class NubFuncType(List<NubType> parameters, NubType returnType) : NubSimpleType
|
||||||
{
|
{
|
||||||
public IReadOnlyList<NubType> Parameters { get; } = parameters;
|
public IReadOnlyList<NubType> Parameters { get; } = parameters;
|
||||||
@@ -139,67 +180,6 @@ public class NubVoidType : NubSimpleType
|
|||||||
public override int GetHashCode() => HashCode.Combine(typeof(NubVoidType));
|
public override int GetHashCode() => HashCode.Combine(typeof(NubVoidType));
|
||||||
}
|
}
|
||||||
|
|
||||||
public class NubPrimitiveType(PrimitiveTypeKind kind) : NubSimpleType
|
|
||||||
{
|
|
||||||
public PrimitiveTypeKind Kind { get; } = kind;
|
|
||||||
|
|
||||||
public override StorageSize StorageSize => Kind switch
|
|
||||||
{
|
|
||||||
PrimitiveTypeKind.I8 => StorageSize.I8,
|
|
||||||
PrimitiveTypeKind.I16 => StorageSize.I16,
|
|
||||||
PrimitiveTypeKind.I32 => StorageSize.I32,
|
|
||||||
PrimitiveTypeKind.I64 => StorageSize.I64,
|
|
||||||
PrimitiveTypeKind.U8 => StorageSize.U8,
|
|
||||||
PrimitiveTypeKind.U16 => StorageSize.U16,
|
|
||||||
PrimitiveTypeKind.U32 => StorageSize.U32,
|
|
||||||
PrimitiveTypeKind.U64 => StorageSize.U64,
|
|
||||||
PrimitiveTypeKind.F64 => StorageSize.F64,
|
|
||||||
PrimitiveTypeKind.F32 => StorageSize.F32,
|
|
||||||
PrimitiveTypeKind.Bool => StorageSize.U8,
|
|
||||||
_ => throw new ArgumentOutOfRangeException()
|
|
||||||
};
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return Kind switch
|
|
||||||
{
|
|
||||||
PrimitiveTypeKind.I8 => "i8",
|
|
||||||
PrimitiveTypeKind.I16 => "i16",
|
|
||||||
PrimitiveTypeKind.I32 => "i32",
|
|
||||||
PrimitiveTypeKind.I64 => "i64",
|
|
||||||
|
|
||||||
PrimitiveTypeKind.U8 => "u8",
|
|
||||||
PrimitiveTypeKind.U16 => "u16",
|
|
||||||
PrimitiveTypeKind.U32 => "u32",
|
|
||||||
PrimitiveTypeKind.U64 => "u64",
|
|
||||||
|
|
||||||
PrimitiveTypeKind.F32 => "f32",
|
|
||||||
PrimitiveTypeKind.F64 => "f64",
|
|
||||||
|
|
||||||
PrimitiveTypeKind.Bool => "bool",
|
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(kind), Kind, null)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool Equals(NubType? other) => other is NubPrimitiveType primitive && primitive.Kind == Kind;
|
|
||||||
public override int GetHashCode() => HashCode.Combine(typeof(NubPrimitiveType), Kind.GetHashCode());
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum PrimitiveTypeKind
|
|
||||||
{
|
|
||||||
I64,
|
|
||||||
I32,
|
|
||||||
I16,
|
|
||||||
I8,
|
|
||||||
U64,
|
|
||||||
U32,
|
|
||||||
U16,
|
|
||||||
U8,
|
|
||||||
F64,
|
|
||||||
F32,
|
|
||||||
Bool
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
public abstract class NubComplexType : NubType;
|
public abstract class NubComplexType : NubType;
|
||||||
@@ -139,7 +139,7 @@ public sealed class TypeChecker
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new If(CheckExpression(statement.Condition, new NubPrimitiveType(PrimitiveTypeKind.Bool)), CheckBlock(statement.Body), elseStatement);
|
return new If(CheckExpression(statement.Condition, new NubBoolType()), CheckBlock(statement.Body), elseStatement);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Return CheckReturn(ReturnSyntax statement)
|
private Return CheckReturn(ReturnSyntax statement)
|
||||||
@@ -188,7 +188,7 @@ public sealed class TypeChecker
|
|||||||
|
|
||||||
private While CheckWhile(WhileSyntax statement)
|
private While CheckWhile(WhileSyntax statement)
|
||||||
{
|
{
|
||||||
return new While(CheckExpression(statement.Condition, new NubPrimitiveType(PrimitiveTypeKind.Bool)), CheckBlock(statement.Body));
|
return new While(CheckExpression(statement.Condition, new NubBoolType()), CheckBlock(statement.Body));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Expression CheckExpression(ExpressionSyntax node, NubType? expectedType = null)
|
private Expression CheckExpression(ExpressionSyntax node, NubType? expectedType = null)
|
||||||
@@ -252,12 +252,12 @@ public sealed class TypeChecker
|
|||||||
{
|
{
|
||||||
var boundArray = CheckExpression(expression.Target);
|
var boundArray = CheckExpression(expression.Target);
|
||||||
var elementType = ((NubArrayType)boundArray.Type).ElementType;
|
var elementType = ((NubArrayType)boundArray.Type).ElementType;
|
||||||
return new ArrayIndexAccess(elementType, boundArray, CheckExpression(expression.Index, new NubPrimitiveType(PrimitiveTypeKind.U64)));
|
return new ArrayIndexAccess(elementType, boundArray, CheckExpression(expression.Index, new NubIntType(false, 64)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private ArrayInitializer CheckArrayInitializer(ArrayInitializerSyntax expression)
|
private ArrayInitializer CheckArrayInitializer(ArrayInitializerSyntax expression)
|
||||||
{
|
{
|
||||||
var capacity = CheckExpression(expression.Capacity, new NubPrimitiveType(PrimitiveTypeKind.U64));
|
var capacity = CheckExpression(expression.Capacity, new NubIntType(false, 64));
|
||||||
var type = new NubArrayType(CheckType(expression.ElementType));
|
var type = new NubArrayType(CheckType(expression.ElementType));
|
||||||
return new ArrayInitializer(type, capacity, CheckType(expression.ElementType));
|
return new ArrayInitializer(type, capacity, CheckType(expression.ElementType));
|
||||||
}
|
}
|
||||||
@@ -346,10 +346,10 @@ public sealed class TypeChecker
|
|||||||
{
|
{
|
||||||
var type = expectedType ?? expression.Kind switch
|
var type = expectedType ?? expression.Kind switch
|
||||||
{
|
{
|
||||||
LiteralKind.Integer => new NubPrimitiveType(PrimitiveTypeKind.I64),
|
LiteralKind.Integer => new NubIntType(true, 64),
|
||||||
LiteralKind.Float => new NubPrimitiveType(PrimitiveTypeKind.F64),
|
LiteralKind.Float => new NubFloatType(64),
|
||||||
LiteralKind.String => new NubStringType(),
|
LiteralKind.String => new NubStringType(),
|
||||||
LiteralKind.Bool => new NubPrimitiveType(PrimitiveTypeKind.Bool),
|
LiteralKind.Bool => new NubBoolType(),
|
||||||
_ => throw new ArgumentOutOfRangeException()
|
_ => throw new ArgumentOutOfRangeException()
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -472,9 +472,9 @@ public sealed class TypeChecker
|
|||||||
{
|
{
|
||||||
case UnaryOperatorSyntax.Negate:
|
case UnaryOperatorSyntax.Negate:
|
||||||
{
|
{
|
||||||
boundOperand = CheckExpression(expression.Operand, new NubPrimitiveType(PrimitiveTypeKind.I64));
|
boundOperand = CheckExpression(expression.Operand, new NubIntType(true, 64));
|
||||||
|
|
||||||
if (boundOperand.Type.IsNumber)
|
if (boundOperand.Type is NubIntType or NubFloatType)
|
||||||
{
|
{
|
||||||
type = boundOperand.Type;
|
type = boundOperand.Type;
|
||||||
}
|
}
|
||||||
@@ -483,9 +483,9 @@ public sealed class TypeChecker
|
|||||||
}
|
}
|
||||||
case UnaryOperatorSyntax.Invert:
|
case UnaryOperatorSyntax.Invert:
|
||||||
{
|
{
|
||||||
boundOperand = CheckExpression(expression.Operand, new NubPrimitiveType(PrimitiveTypeKind.Bool));
|
boundOperand = CheckExpression(expression.Operand, new NubBoolType());
|
||||||
|
|
||||||
type = new NubPrimitiveType(PrimitiveTypeKind.Bool);
|
type = new NubBoolType();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -574,25 +574,13 @@ public sealed class TypeChecker
|
|||||||
return node switch
|
return node switch
|
||||||
{
|
{
|
||||||
ArrayTypeSyntax type => new NubArrayType(CheckType(type.BaseType)),
|
ArrayTypeSyntax type => new NubArrayType(CheckType(type.BaseType)),
|
||||||
|
BoolTypeSyntax => new NubBoolType(),
|
||||||
CStringTypeSyntax => new NubCStringType(),
|
CStringTypeSyntax => new NubCStringType(),
|
||||||
CustomTypeSyntax type => new NubCustomType(type.MangledName()),
|
CustomTypeSyntax type => new NubCustomType(type.MangledName()),
|
||||||
|
FloatTypeSyntax @float => new NubFloatType(@float.Width),
|
||||||
FuncTypeSyntax type => new NubFuncType(type.Parameters.Select(CheckType).ToList(), CheckType(type.ReturnType)),
|
FuncTypeSyntax type => new NubFuncType(type.Parameters.Select(CheckType).ToList(), CheckType(type.ReturnType)),
|
||||||
|
IntTypeSyntax @int => new NubIntType(@int.Signed, @int.Width),
|
||||||
PointerTypeSyntax type => new NubPointerType(CheckType(type.BaseType)),
|
PointerTypeSyntax type => new NubPointerType(CheckType(type.BaseType)),
|
||||||
PrimitiveTypeSyntax type => new NubPrimitiveType(type.SyntaxKind switch
|
|
||||||
{
|
|
||||||
PrimitiveTypeSyntaxKind.I64 => PrimitiveTypeKind.I64,
|
|
||||||
PrimitiveTypeSyntaxKind.I32 => PrimitiveTypeKind.I32,
|
|
||||||
PrimitiveTypeSyntaxKind.I16 => PrimitiveTypeKind.I16,
|
|
||||||
PrimitiveTypeSyntaxKind.I8 => PrimitiveTypeKind.I8,
|
|
||||||
PrimitiveTypeSyntaxKind.U64 => PrimitiveTypeKind.U64,
|
|
||||||
PrimitiveTypeSyntaxKind.U32 => PrimitiveTypeKind.U32,
|
|
||||||
PrimitiveTypeSyntaxKind.U16 => PrimitiveTypeKind.U16,
|
|
||||||
PrimitiveTypeSyntaxKind.U8 => PrimitiveTypeKind.U8,
|
|
||||||
PrimitiveTypeSyntaxKind.F64 => PrimitiveTypeKind.F64,
|
|
||||||
PrimitiveTypeSyntaxKind.F32 => PrimitiveTypeKind.F32,
|
|
||||||
PrimitiveTypeSyntaxKind.Bool => PrimitiveTypeKind.Bool,
|
|
||||||
_ => throw new ArgumentOutOfRangeException()
|
|
||||||
}),
|
|
||||||
StringTypeSyntax => new NubStringType(),
|
StringTypeSyntax => new NubStringType(),
|
||||||
VoidTypeSyntax => new NubVoidType(),
|
VoidTypeSyntax => new NubVoidType(),
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(node))
|
_ => throw new ArgumentOutOfRangeException(nameof(node))
|
||||||
|
|||||||
Reference in New Issue
Block a user