This commit is contained in:
nub31
2025-05-12 21:41:00 +02:00
parent b4a80bb7e1
commit 90ef9fb8e8
8 changed files with 186 additions and 329 deletions

View File

@@ -2,6 +2,5 @@
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/../.." vcs="Git" />
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
</component>
</project>

View File

@@ -44,22 +44,64 @@ public class Generator
private string QbeTypeName(NubType type)
{
if (type.Equals(NubType.Int32) || type.Equals(NubType.Bool))
if (type is NubPrimitiveType primitiveType)
{
return "w";
switch (primitiveType.Kind)
{
case PrimitiveTypeKind.I64:
case PrimitiveTypeKind.U64:
case PrimitiveTypeKind.String:
case PrimitiveTypeKind.Any:
return "l";
case PrimitiveTypeKind.I32:
case PrimitiveTypeKind.U32:
case PrimitiveTypeKind.I16:
case PrimitiveTypeKind.U16:
case PrimitiveTypeKind.I8:
case PrimitiveTypeKind.U8:
case PrimitiveTypeKind.Bool:
return "w";
case PrimitiveTypeKind.F64:
return "d";
case PrimitiveTypeKind.F32:
return "s";
default:
throw new ArgumentOutOfRangeException();
}
}
return "l";
throw new NotImplementedException();
}
private int QbeTypeSize(NubType type)
{
if (type.Equals(NubType.Int32) || type.Equals(NubType.Bool))
if (type is NubPrimitiveType primitiveType)
{
return 4;
switch (primitiveType.Kind)
{
case PrimitiveTypeKind.I64:
case PrimitiveTypeKind.U64:
case PrimitiveTypeKind.String:
case PrimitiveTypeKind.Any:
return 8;
case PrimitiveTypeKind.I32:
case PrimitiveTypeKind.U32:
case PrimitiveTypeKind.I16:
case PrimitiveTypeKind.U16:
case PrimitiveTypeKind.I8:
case PrimitiveTypeKind.U8:
case PrimitiveTypeKind.Bool:
return 4;
case PrimitiveTypeKind.F64:
return 8;
case PrimitiveTypeKind.F32:
return 4;
default:
throw new ArgumentOutOfRangeException();
}
}
return 8;
throw new NotImplementedException();
}
private void GenerateFuncDefinition(LocalFuncDefinitionNode node)
@@ -349,25 +391,25 @@ public class Generator
{
case BinaryExpressionOperator.Equal:
{
if (binaryExpression.Left.Type.Equals(NubType.Int64) && binaryExpression.Right.Type.Equals(NubType.Int64))
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I64))
{
_builder.AppendLine($" %{outputLabel} =w ceql {left}, {right}");
return $"%{outputLabel}";
}
if (binaryExpression.Left.Type.Equals(NubType.Int32) && binaryExpression.Right.Type.Equals(NubType.Int32))
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I32))
{
_builder.AppendLine($" %{outputLabel} =w ceqw {left}, {right}");
return $"%{outputLabel}";
}
if (binaryExpression.Left.Type.Equals(NubType.String) && binaryExpression.Right.Type.Equals(NubType.String))
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.String))
{
_builder.AppendLine($" %{outputLabel} =w call $nub_strcmp(l {left}, l {right})");
return $"%{outputLabel}";
}
if (binaryExpression.Left.Type.Equals(NubType.Bool) && binaryExpression.Right.Type.Equals(NubType.Bool))
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.Bool))
{
_builder.AppendLine($" %{outputLabel} =w ceqw {left}, {right}");
return $"%{outputLabel}";
@@ -376,26 +418,26 @@ public class Generator
}
case BinaryExpressionOperator.NotEqual:
{
if (binaryExpression.Left.Type.Equals(NubType.Int64) && binaryExpression.Right.Type.Equals(NubType.Int64))
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I64))
{
_builder.AppendLine($" %{outputLabel} =w cnel {left}, {right}");
return $"%{outputLabel}";
}
if (binaryExpression.Left.Type.Equals(NubType.Int32) && binaryExpression.Right.Type.Equals(NubType.Int32))
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I32))
{
_builder.AppendLine($" %{outputLabel} =w cnew {left}, {right}");
return $"%{outputLabel}";
}
if (binaryExpression.Left.Type.Equals(NubType.String) && binaryExpression.Right.Type.Equals(NubType.String))
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.String))
{
_builder.AppendLine($" %{outputLabel} =w call $nub_strcmp(l {left}, l {right})");
_builder.AppendLine($" %{outputLabel} =w xor %{outputLabel}, 1");
return $"%{outputLabel}";
}
if (binaryExpression.Left.Type.Equals(NubType.Bool) && binaryExpression.Right.Type.Equals(NubType.Bool))
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.Bool))
{
_builder.AppendLine($" %{outputLabel} =w cnew {left}, {right}");
return $"%{outputLabel}";
@@ -404,19 +446,19 @@ public class Generator
}
case BinaryExpressionOperator.GreaterThan:
{
if (binaryExpression.Left.Type.Equals(NubType.Int64) && binaryExpression.Right.Type.Equals(NubType.Int64))
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I64))
{
_builder.AppendLine($" %{outputLabel} =w csgtl {left}, {right}");
return $"%{outputLabel}";
}
if (binaryExpression.Left.Type.Equals(NubType.Int32) && binaryExpression.Right.Type.Equals(NubType.Int32))
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I32))
{
_builder.AppendLine($" %{outputLabel} =w csgtw {left}, {right}");
return $"%{outputLabel}";
}
if (binaryExpression.Left.Type.Equals(NubType.Bool) && binaryExpression.Right.Type.Equals(NubType.Bool))
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.Bool))
{
_builder.AppendLine($" %{outputLabel} =w csgtw {left}, {right}");
return $"%{outputLabel}";
@@ -425,19 +467,19 @@ public class Generator
}
case BinaryExpressionOperator.GreaterThanOrEqual:
{
if (binaryExpression.Left.Type.Equals(NubType.Int64) && binaryExpression.Right.Type.Equals(NubType.Int64))
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I64))
{
_builder.AppendLine($" %{outputLabel} =w csgel {left}, {right}");
return $"%{outputLabel}";
}
if (binaryExpression.Left.Type.Equals(NubType.Int32) && binaryExpression.Right.Type.Equals(NubType.Int32))
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I32))
{
_builder.AppendLine($" %{outputLabel} =w csgew {left}, {right}");
return $"%{outputLabel}";
}
if (binaryExpression.Left.Type.Equals(NubType.Bool) && binaryExpression.Right.Type.Equals(NubType.Bool))
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.Bool))
{
_builder.AppendLine($" %{outputLabel} =w csgew {left}, {right}");
return $"%{outputLabel}";
@@ -446,19 +488,19 @@ public class Generator
}
case BinaryExpressionOperator.LessThan:
{
if (binaryExpression.Left.Type.Equals(NubType.Int64) && binaryExpression.Right.Type.Equals(NubType.Int64))
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I64))
{
_builder.AppendLine($" %{outputLabel} =w csltl {left}, {right}");
return $"%{outputLabel}";
}
if (binaryExpression.Left.Type.Equals(NubType.Int32) && binaryExpression.Right.Type.Equals(NubType.Int32))
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I32))
{
_builder.AppendLine($" %{outputLabel} =w csltw {left}, {right}");
return $"%{outputLabel}";
}
if (binaryExpression.Left.Type.Equals(NubType.Bool) && binaryExpression.Right.Type.Equals(NubType.Bool))
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.Bool))
{
_builder.AppendLine($" %{outputLabel} =w csltw {left}, {right}");
return $"%{outputLabel}";
@@ -467,19 +509,19 @@ public class Generator
}
case BinaryExpressionOperator.LessThanOrEqual:
{
if (binaryExpression.Left.Type.Equals(NubType.Int64) && binaryExpression.Right.Type.Equals(NubType.Int64))
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I64))
{
_builder.AppendLine($" %{outputLabel} =w cslel {left}, {right}");
return $"%{outputLabel}";
}
if (binaryExpression.Left.Type.Equals(NubType.Int32) && binaryExpression.Right.Type.Equals(NubType.Int32))
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I32))
{
_builder.AppendLine($" %{outputLabel} =w cslew {left}, {right}");
return $"%{outputLabel}";
}
if (binaryExpression.Left.Type.Equals(NubType.Bool) && binaryExpression.Right.Type.Equals(NubType.Bool))
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.Bool))
{
_builder.AppendLine($" %{outputLabel} =w cslew {left}, {right}");
return $"%{outputLabel}";
@@ -488,13 +530,13 @@ public class Generator
}
case BinaryExpressionOperator.Plus:
{
if (binaryExpression.Left.Type.Equals(NubType.Int64) && binaryExpression.Right.Type.Equals(NubType.Int64))
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I64))
{
_builder.AppendLine($" %{outputLabel} =l add {left}, {right}");
return $"%{outputLabel}";
}
if (binaryExpression.Left.Type.Equals(NubType.Int32) && binaryExpression.Right.Type.Equals(NubType.Int32))
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I32))
{
_builder.AppendLine($" %{outputLabel} =w add {left}, {right}");
return $"%{outputLabel}";
@@ -503,13 +545,13 @@ public class Generator
}
case BinaryExpressionOperator.Minus:
{
if (binaryExpression.Left.Type.Equals(NubType.Int64) && binaryExpression.Right.Type.Equals(NubType.Int64))
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I64))
{
_builder.AppendLine($" %{outputLabel} =l sub {left}, {right}");
return $"%{outputLabel}";
}
if (binaryExpression.Left.Type.Equals(NubType.Int32) && binaryExpression.Right.Type.Equals(NubType.Int32))
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I32))
{
_builder.AppendLine($" %{outputLabel} =w sub {left}, {right}");
return $"%{outputLabel}";
@@ -518,13 +560,13 @@ public class Generator
}
case BinaryExpressionOperator.Multiply:
{
if (binaryExpression.Left.Type.Equals(NubType.Int64) && binaryExpression.Right.Type.Equals(NubType.Int64))
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I64))
{
_builder.AppendLine($" %{outputLabel} =l mul {left}, {right}");
return $"%{outputLabel}";
}
if (binaryExpression.Left.Type.Equals(NubType.Int32) && binaryExpression.Right.Type.Equals(NubType.Int32))
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I32))
{
_builder.AppendLine($" %{outputLabel} =w mul {left}, {right}");
return $"%{outputLabel}";
@@ -533,13 +575,13 @@ public class Generator
}
case BinaryExpressionOperator.Divide:
{
if (binaryExpression.Left.Type.Equals(NubType.Int64) && binaryExpression.Right.Type.Equals(NubType.Int64))
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I64))
{
_builder.AppendLine($" %{outputLabel} =l div {left}, {right}");
return $"%{outputLabel}";
}
if (binaryExpression.Left.Type.Equals(NubType.Int32) && binaryExpression.Right.Type.Equals(NubType.Int32))
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I32))
{
_builder.AppendLine($" %{outputLabel} =w div {left}, {right}");
return $"%{outputLabel}";
@@ -562,18 +604,18 @@ public class Generator
private string GenerateLiteral(LiteralNode literal)
{
if (literal.LiteralType.Equals(NubType.String))
if (literal.LiteralType.Equals(NubPrimitiveType.String))
{
_strings.Add(literal.Literal);
return $"$str{_strings.Count}";
}
if (literal.LiteralType.Equals(NubType.Int64) || literal.LiteralType.Equals(NubType.Int32))
if (literal.LiteralType.Equals(NubPrimitiveType.I64) || literal.LiteralType.Equals(NubPrimitiveType.I32))
{
return literal.Literal;
}
if (literal.LiteralType.Equals(NubType.Bool))
if (literal.LiteralType.Equals(NubPrimitiveType.Bool))
{
return bool.Parse(literal.Literal) ? "1" : "0";
}

View File

@@ -86,7 +86,7 @@ public class Lexer
if (buffer is "true" or "false")
{
return new LiteralToken(NubType.Bool, buffer);
return new LiteralToken(NubPrimitiveType.Bool, buffer);
}
return new IdentifierToken(buffer);
@@ -103,7 +103,7 @@ public class Lexer
current = Peek();
}
return new LiteralToken(NubType.Int64, buffer);
return new LiteralToken(NubPrimitiveType.I64, buffer);
}
// TODO: Revisit this
@@ -148,7 +148,7 @@ public class Lexer
buffer += current.Value;
}
return new LiteralToken(NubType.String, buffer);
return new LiteralToken(NubPrimitiveType.String, buffer);
}
if (char.IsWhiteSpace(current.Value))

View File

@@ -20,12 +20,7 @@ public class Parser
{
if (TryExpectSymbol(Symbol.Import))
{
var name = ExpectLiteral();
if (!name.Type.Equals(NubType.String))
{
throw new Exception("Import statements must have a string literal value");
}
var name = ExpectIdentifier();
TryExpectSymbol(Symbol.Semicolon);
imports.Add(name.Value);
}
@@ -466,7 +461,7 @@ public class Parser
private NubType ParseType()
{
var name = ExpectIdentifier().Value;
return new NubType(name);
return NubType.Parse(name);
}
private Token ExpectToken()

View File

@@ -197,7 +197,7 @@ public class ExpressionTyper
case BinaryExpressionOperator.LessThan:
case BinaryExpressionOperator.LessThanOrEqual:
{
binaryExpression.Type = new NubType("bool");
binaryExpression.Type = NubPrimitiveType.Bool;
break;
}
case BinaryExpressionOperator.Plus:

View File

@@ -1,32 +1,117 @@
namespace Nub.Lang;
using System.Diagnostics.CodeAnalysis;
public sealed class NubType
namespace Nub.Lang;
public abstract class NubType
{
public NubType(string name)
protected NubType(string name)
{
Name = name;
}
public string Name { get; }
public static NubType Int64 => new("i64");
public static NubType Int32 => new("i32");
public static NubType Bool => new("bool");
public static NubType String => new("string");
public static NubType Any => new("any");
public override bool Equals(object? obj)
public static NubType Parse(string s)
{
return obj is NubType item && Name.Equals(item.Name);
if (NubPrimitiveType.TryParse(s, out var kind))
{
return new NubPrimitiveType(kind.Value);
}
return new NubCustomType(s);
}
public override int GetHashCode()
public override bool Equals(object? obj) => obj is NubType item && Name.Equals(item.Name);
public override int GetHashCode() => HashCode.Combine(Name);
public override string ToString() => Name;
}
public class NubCustomType(string name) : NubType(name);
public class NubPrimitiveType : NubType
{
public NubPrimitiveType(PrimitiveTypeKind kind) : base(KindToString(kind))
{
return HashCode.Combine(Name);
Kind = kind;
}
public override string ToString()
public PrimitiveTypeKind Kind { get; }
public static NubPrimitiveType I64 => new(PrimitiveTypeKind.I64);
public static NubPrimitiveType I32 => new(PrimitiveTypeKind.I32);
public static NubPrimitiveType I16 => new(PrimitiveTypeKind.I16);
public static NubPrimitiveType I8 => new(PrimitiveTypeKind.I8);
public static NubPrimitiveType U64 => new(PrimitiveTypeKind.U64);
public static NubPrimitiveType U32 => new(PrimitiveTypeKind.U32);
public static NubPrimitiveType U16 => new(PrimitiveTypeKind.U16);
public static NubPrimitiveType U8 => new(PrimitiveTypeKind.U8);
public static NubPrimitiveType F64 => new(PrimitiveTypeKind.F64);
public static NubPrimitiveType F32 => new(PrimitiveTypeKind.F32);
public static NubPrimitiveType Bool => new(PrimitiveTypeKind.Bool);
public static NubPrimitiveType String => new(PrimitiveTypeKind.String);
public static NubPrimitiveType Any => new(PrimitiveTypeKind.Any);
public static bool TryParse(string s, [NotNullWhen(true)] out PrimitiveTypeKind? kind)
{
return $"{Name}";
kind = s switch
{
"i64" => PrimitiveTypeKind.I64,
"i32" => PrimitiveTypeKind.I32,
"i16" => PrimitiveTypeKind.I16,
"i8" => PrimitiveTypeKind.I8,
"u64" => PrimitiveTypeKind.U64,
"u32" => PrimitiveTypeKind.U32,
"u16" => PrimitiveTypeKind.U16,
"u8" => PrimitiveTypeKind.U8,
"f64" => PrimitiveTypeKind.F64,
"f32" => PrimitiveTypeKind.F32,
"bool" => PrimitiveTypeKind.Bool,
"string" => PrimitiveTypeKind.String,
"any" => PrimitiveTypeKind.Any,
_ => null
};
return kind != null;
}
public static string KindToString(PrimitiveTypeKind kind)
{
return kind switch
{
PrimitiveTypeKind.I64 => "i64",
PrimitiveTypeKind.I32 => "i32",
PrimitiveTypeKind.I16 => "i16",
PrimitiveTypeKind.I8 => "i8",
PrimitiveTypeKind.U64 => "u64",
PrimitiveTypeKind.U32 => "u32",
PrimitiveTypeKind.U16 => "u16",
PrimitiveTypeKind.U8 => "u8",
PrimitiveTypeKind.F64 => "f64",
PrimitiveTypeKind.F32 => "f32",
PrimitiveTypeKind.Bool => "bool",
PrimitiveTypeKind.String => "string",
PrimitiveTypeKind.Any => "any",
_ => throw new ArgumentOutOfRangeException(nameof(kind), kind, null)
};
}
}
public enum PrimitiveTypeKind
{
I64,
I32,
I16,
I8,
U64,
U32,
U16,
U8,
F64,
F32,
Bool,
String,
Any
}