Primitive to int/float/bool

This commit is contained in:
nub31
2025-07-24 18:39:13 +02:00
parent 07ee11210c
commit cf01cc2aaa
7 changed files with 146 additions and 148 deletions

View File

@@ -1,5 +1,5 @@
func main(args: []cstring): i64 func main(args: []cstring): i64
{ {
puts("test" =) puts("test")
return 0 return 0
} }

View File

@@ -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);
} }

View File

@@ -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)
}; };
} }

View File

@@ -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() => [];
} }
@@ -89,3 +81,8 @@ 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() => [];
}

View File

@@ -1,4 +1,5 @@
using NubLang.Parsing.Syntax; using NubLang.Parsing.Syntax;
using NubLang.TypeChecking.Node;
namespace NubLang.TypeChecking; namespace NubLang.TypeChecking;

View File

@@ -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;

View File

@@ -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))