Some cleanup

This commit is contained in:
nub31
2025-10-16 15:48:04 +02:00
parent f7f32b8d23
commit bbbdf42c47
10 changed files with 95 additions and 1510 deletions

View File

@@ -1,29 +0,0 @@
using System.Diagnostics;
namespace NubLang.CLI;
public static class Archive
{
public static async Task<bool> Invoke(string fileName, params IEnumerable<string> objectFiles)
{
using var process = new Process();
process.StartInfo = new ProcessStartInfo("ar", ["rcs", fileName, ..objectFiles])
{
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true
};
process.Start();
await process.WaitForExitAsync();
var errors = await process.StandardError.ReadToEndAsync();
if (!string.IsNullOrWhiteSpace(errors))
{
await Console.Error.WriteLineAsync(errors);
}
return process.ExitCode == 0;
}
}

View File

@@ -1,54 +0,0 @@
using System.Diagnostics;
namespace NubLang.CLI;
public static class GCC
{
public static async Task<bool> Assemble(string asmPath, string outPath)
{
using var process = new Process();
process.StartInfo = new ProcessStartInfo("x86_64-elf-as", ["-nostartfiles", "-o", outPath, asmPath])
{
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true
};
process.Start();
await process.WaitForExitAsync();
var errors = await process.StandardError.ReadToEndAsync();
if (!string.IsNullOrWhiteSpace(errors))
{
await Console.Error.WriteLineAsync(errors);
}
return process.ExitCode == 0;
}
public static async Task<bool> Compile(string cPath, string outPath)
{
using var process = new Process();
process.StartInfo = new ProcessStartInfo("gcc", ["-ffreestanding", "-nostartfiles", "-c", "-o", outPath, cPath])
{
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true
};
process.Start();
await process.WaitForExitAsync();
var errors = await process.StandardError.ReadToEndAsync();
if (!string.IsNullOrWhiteSpace(errors))
{
await Console.Error.WriteLineAsync(errors);
}
return process.ExitCode == 0;
}
}

View File

@@ -6,8 +6,6 @@ using NubLang.Generation;
using NubLang.Modules; using NubLang.Modules;
using NubLang.Syntax; using NubLang.Syntax;
var sw = Stopwatch.StartNew();
var options = new Options(); var options = new Options();
for (var i = 0; i < args.Length; i++) for (var i = 0; i < args.Length; i++)
@@ -34,9 +32,6 @@ for (var i = 0; i < args.Length; i++)
} }
} }
Console.WriteLine($"Parse cli args: {sw.ElapsedMilliseconds}ms");
sw.Restart();
foreach (var file in options.Files) foreach (var file in options.Files)
{ {
if (!File.Exists(file)) if (!File.Exists(file))
@@ -46,9 +41,6 @@ foreach (var file in options.Files)
} }
} }
Console.WriteLine($"Check file exists: {sw.ElapsedMilliseconds}ms");
sw.Restart();
var diagnostics = new List<Diagnostic>(); var diagnostics = new List<Diagnostic>();
var syntaxTrees = new List<SyntaxTree>(); var syntaxTrees = new List<SyntaxTree>();
@@ -58,26 +50,15 @@ foreach (var file in options.Files)
tokenizer.Tokenize(); tokenizer.Tokenize();
diagnostics.AddRange(tokenizer.Diagnostics); diagnostics.AddRange(tokenizer.Diagnostics);
Console.WriteLine($" Tokenize: {Path.GetFileName(file)}: {sw.ElapsedMilliseconds}ms");
sw.Restart();
var parser = new Parser(); var parser = new Parser();
var syntaxTree = parser.Parse(tokenizer.Tokens); var syntaxTree = parser.Parse(tokenizer.Tokens);
diagnostics.AddRange(parser.Diagnostics); diagnostics.AddRange(parser.Diagnostics);
Console.WriteLine($" Parse: {Path.GetFileName(file)}: {sw.ElapsedMilliseconds}ms");
sw.Restart();
syntaxTrees.Add(syntaxTree); syntaxTrees.Add(syntaxTree);
} }
sw.Restart();
var moduleRepository = new ModuleRepository(syntaxTrees); var moduleRepository = new ModuleRepository(syntaxTrees);
Console.WriteLine($"Create module repository: {sw.ElapsedMilliseconds}ms");
sw.Restart();
var definitions = new List<DefinitionNode>(); var definitions = new List<DefinitionNode>();
var referencedStructTypes = new HashSet<NubStructType>(); var referencedStructTypes = new HashSet<NubStructType>();
@@ -87,9 +68,6 @@ foreach (var syntaxTree in syntaxTrees)
var typeChecker = new TypeChecker(syntaxTree, moduleRepository); var typeChecker = new TypeChecker(syntaxTree, moduleRepository);
typeChecker.Check(); typeChecker.Check();
Console.WriteLine($" Type check {syntaxTree.Metadata.ModuleName}: {sw.ElapsedMilliseconds}ms");
sw.Restart();
definitions.AddRange(typeChecker.Definitions); definitions.AddRange(typeChecker.Definitions);
diagnostics.AddRange(typeChecker.Diagnostics); diagnostics.AddRange(typeChecker.Diagnostics);
@@ -99,16 +77,11 @@ foreach (var syntaxTree in syntaxTrees)
} }
} }
sw.Restart();
foreach (var diagnostic in diagnostics) foreach (var diagnostic in diagnostics)
{ {
Console.Error.WriteLine(diagnostic.FormatANSI()); Console.Error.WriteLine(diagnostic.FormatANSI());
} }
Console.WriteLine($"Print diagnostics: {sw.ElapsedMilliseconds}ms");
sw.Restart();
if (diagnostics.Any(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error)) if (diagnostics.Any(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error))
{ {
return 1; return 1;
@@ -116,38 +89,20 @@ if (diagnostics.Any(diagnostic => diagnostic.Severity == DiagnosticSeverity.Erro
Directory.CreateDirectory(".build"); Directory.CreateDirectory(".build");
var generator = new CGenerator(definitions, referencedStructTypes); var generator = new Generator(definitions, referencedStructTypes);
var c = generator.Emit(); var c = generator.Emit();
var cFilePath = Path.Combine(".build", "out.c"); var cFilePath = Path.Combine(".build", "out.c");
File.WriteAllText(cFilePath, c); File.WriteAllText(cFilePath, c);
var objFilePath = Path.Combine(".build", "out.o"); using var process = Process.Start("gcc", ["-ffreestanding", "-nostartfiles", "-c", "-o", Path.Combine(".build", "out.o"), cFilePath]);
var asmSuccess = await GCC.Compile(cFilePath, objFilePath);
if (!asmSuccess) return 1;
// sw.Restart(); process.WaitForExit();
//
// var generator = new QBEGenerator(definitions, referencedStructTypes); if (process.ExitCode != 0)
// var ssa = generator.Emit(); {
// var ssaFilePath = Path.Combine(".build", "out.ssa"); Console.Error.WriteLine($"gcc failed with exit code {process.ExitCode}");
// File.WriteAllText(ssaFilePath, ssa); return 1;
// }
// Console.WriteLine($"Emit ssa: {sw.ElapsedMilliseconds}ms");
// sw.Restart();
//
// var asmFilePath = Path.Combine(".build", "out.asm");
// var qbeSuccess = await QBE.Invoke(ssaFilePath, asmFilePath);
// if (!qbeSuccess) return 1;
//
// Console.WriteLine($"Emit asm: {sw.ElapsedMilliseconds}ms");
// sw.Restart();
//
// var objFilePath = Path.Combine(".build", "out.o");
// var asmSuccess = await GCC.Assemble(asmFilePath, objFilePath);
// if (!asmSuccess) return 1;
//
// Console.WriteLine($"Assemble: {sw.ElapsedMilliseconds}ms");
sw.Restart();
return 0; return 0;

View File

@@ -1,30 +0,0 @@
using System.Diagnostics;
namespace NubLang.CLI;
public static class QBE
{
public static async Task<bool> Invoke(string ssaPath, string outPath)
{
using var process = new Process();
process.StartInfo = new ProcessStartInfo("qbe", ["-o", outPath, ssaPath])
{
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true
};
process.Start();
await process.WaitForExitAsync();
var errors = await process.StandardError.ReadToEndAsync();
if (!string.IsNullOrWhiteSpace(errors))
{
await Console.Error.WriteLineAsync(errors);
}
return process.ExitCode == 0;
}
}

View File

@@ -126,7 +126,7 @@ public record StructFieldAccessNode(NubType Type, ExpressionNode Target, string
public record StructInitializerNode(NubStructType StructType, Dictionary<string, ExpressionNode> Initializers) : RValueExpressionNode(StructType); public record StructInitializerNode(NubStructType StructType, Dictionary<string, ExpressionNode> Initializers) : RValueExpressionNode(StructType);
public record DereferenceNode(NubType Type, ExpressionNode Expression) : LValueExpressionNode(Type); public record DereferenceNode(NubType Type, ExpressionNode Target) : LValueExpressionNode(Type);
public record ConvertIntNode(NubType Type, ExpressionNode Value, NubIntType ValueType, NubIntType TargetType) : RValueExpressionNode(Type); public record ConvertIntNode(NubType Type, ExpressionNode Value, NubIntType ValueType, NubIntType TargetType) : RValueExpressionNode(Type);

View File

@@ -2,17 +2,17 @@ using NubLang.Ast;
namespace NubLang.Generation; namespace NubLang.Generation;
public class CGenerator public class Generator
{ {
private readonly List<DefinitionNode> _definitions; private readonly List<DefinitionNode> _definitions;
private readonly HashSet<NubStructType> _structTypes; private readonly HashSet<NubStructType> _structTypes;
private readonly CWriter _writer; private readonly IndentedTextWriter _writer;
public CGenerator(List<DefinitionNode> definitions, HashSet<NubStructType> structTypes) public Generator(List<DefinitionNode> definitions, HashSet<NubStructType> structTypes)
{ {
_definitions = definitions; _definitions = definitions;
_structTypes = structTypes; _structTypes = structTypes;
_writer = new CWriter(); _writer = new IndentedTextWriter();
} }
private static string MapType(NubType nubType) private static string MapType(NubType nubType)
@@ -114,7 +114,6 @@ public class CGenerator
"""); """);
_writer.WriteLine(); _writer.WriteLine();
_writer.WriteLine("// Struct definitions");
foreach (var structType in _structTypes) foreach (var structType in _structTypes)
{ {
_writer.WriteLine("typedef struct"); _writer.WriteLine("typedef struct");
@@ -131,9 +130,11 @@ public class CGenerator
_writer.WriteLine(); _writer.WriteLine();
} }
_writer.WriteLine("// Function declarations"); var appendNewLine = false;
foreach (var funcNode in _definitions.OfType<FuncNode>()) foreach (var funcNode in _definitions.OfType<FuncNode>())
{ {
appendNewLine = true;
var parameters = funcNode.Signature.Parameters.Count != 0 var parameters = funcNode.Signature.Parameters.Count != 0
? string.Join(", ", funcNode.Signature.Parameters.Select(x => $"{MapType(x.Type)} {x.Name}")) ? string.Join(", ", funcNode.Signature.Parameters.Select(x => $"{MapType(x.Type)} {x.Name}"))
: "void"; : "void";
@@ -142,12 +143,13 @@ public class CGenerator
_writer.WriteLine($"{MapType(funcNode.Signature.ReturnType)} {name}({parameters});"); _writer.WriteLine($"{MapType(funcNode.Signature.ReturnType)} {name}({parameters});");
} }
_writer.WriteLine(); if (appendNewLine)
{
_writer.WriteLine();
}
_writer.WriteLine("// Struct function implementations");
foreach (var structNode in _definitions.OfType<StructNode>()) foreach (var structNode in _definitions.OfType<StructNode>())
{ {
_writer.WriteLine($"// {structNode.Module}::{structNode.Name}");
foreach (var structFuncNode in structNode.Functions) foreach (var structFuncNode in structNode.Functions)
{ {
var parameters = structFuncNode.Signature.Parameters.Count != 0 var parameters = structFuncNode.Signature.Parameters.Count != 0
@@ -157,12 +159,10 @@ public class CGenerator
var name = StructFuncName(structNode.Module, structNode.Name, structFuncNode.Name); var name = StructFuncName(structNode.Module, structNode.Name, structFuncNode.Name);
_writer.WriteLine($"{MapType(structFuncNode.Signature.ReturnType)} {name}({parameters})"); _writer.WriteLine($"{MapType(structFuncNode.Signature.ReturnType)} {name}({parameters})");
EmitBlock(structFuncNode.Body); EmitBlock(structFuncNode.Body);
_writer.WriteLine();
} }
} }
_writer.WriteLine();
_writer.WriteLine("// Function implementations");
foreach (var funcNode in _definitions.OfType<FuncNode>()) foreach (var funcNode in _definitions.OfType<FuncNode>())
{ {
if (funcNode.Body == null) continue; if (funcNode.Body == null) continue;
@@ -229,7 +229,9 @@ public class CGenerator
private void EmitAssignment(AssignmentNode assignmentNode) private void EmitAssignment(AssignmentNode assignmentNode)
{ {
throw new NotImplementedException(); var target = EmitExpression(assignmentNode.Target);
var value = EmitExpression(assignmentNode.Value);
_writer.WriteLine($"{target} = {value};");
} }
private void EmitBreak(BreakNode breakNode) private void EmitBreak(BreakNode breakNode)
@@ -314,7 +316,7 @@ public class CGenerator
private string EmitExpression(ExpressionNode expressionNode) private string EmitExpression(ExpressionNode expressionNode)
{ {
return expressionNode switch var expr = expressionNode switch
{ {
ArrayIndexAccessNode arrayIndexAccessNode => EmitArrayIndexAccess(arrayIndexAccessNode), ArrayIndexAccessNode arrayIndexAccessNode => EmitArrayIndexAccess(arrayIndexAccessNode),
ArrayInitializerNode arrayInitializerNode => EmitArrayInitializer(arrayInitializerNode), ArrayInitializerNode arrayInitializerNode => EmitArrayInitializer(arrayInitializerNode),
@@ -342,21 +344,53 @@ public class CGenerator
UnaryExpressionNode unaryExpressionNode => EmitUnaryExpression(unaryExpressionNode), UnaryExpressionNode unaryExpressionNode => EmitUnaryExpression(unaryExpressionNode),
_ => throw new ArgumentOutOfRangeException(nameof(expressionNode)) _ => throw new ArgumentOutOfRangeException(nameof(expressionNode))
}; };
return $"({expr})";
} }
private string EmitArrayIndexAccess(ArrayIndexAccessNode arrayIndexAccessNode) private string EmitArrayIndexAccess(ArrayIndexAccessNode arrayIndexAccessNode)
{ {
throw new NotImplementedException(); var array = EmitExpression(arrayIndexAccessNode.Target);
var index = EmitExpression(arrayIndexAccessNode.Index);
return $"(({MapType(arrayIndexAccessNode.Type)}*){array})[{index}]";
} }
private string EmitArrayInitializer(ArrayInitializerNode arrayInitializerNode) private string EmitArrayInitializer(ArrayInitializerNode arrayInitializerNode)
{ {
throw new NotImplementedException(); var capacity = EmitExpression(arrayInitializerNode.Capacity);
var elementType = MapType(arrayInitializerNode.ElementType);
return $"({elementType}[{capacity}]){{0}}";
} }
private string EmitBinaryExpression(BinaryExpressionNode binaryExpressionNode) private string EmitBinaryExpression(BinaryExpressionNode binaryExpressionNode)
{ {
throw new NotImplementedException(); var left = EmitExpression(binaryExpressionNode.Left);
var right = EmitExpression(binaryExpressionNode.Right);
var op = binaryExpressionNode.Operator switch
{
BinaryOperator.Plus => "+",
BinaryOperator.Minus => "-",
BinaryOperator.Multiply => "*",
BinaryOperator.Divide => "/",
BinaryOperator.Modulo => "%",
BinaryOperator.Equal => "==",
BinaryOperator.NotEqual => "!=",
BinaryOperator.LessThan => "<",
BinaryOperator.LessThanOrEqual => "<=",
BinaryOperator.GreaterThan => ">",
BinaryOperator.GreaterThanOrEqual => ">=",
BinaryOperator.LogicalAnd => "&&",
BinaryOperator.LogicalOr => "||",
BinaryOperator.BitwiseAnd => "&",
BinaryOperator.BitwiseOr => "|",
BinaryOperator.BitwiseXor => "^",
BinaryOperator.LeftShift => "<<",
BinaryOperator.RightShift => ">>",
_ => throw new ArgumentOutOfRangeException()
};
return $"{left} {op} {right}";
} }
private string EmitBoolLiteral(BoolLiteralNode boolLiteralNode) private string EmitBoolLiteral(BoolLiteralNode boolLiteralNode)
@@ -366,12 +400,14 @@ public class CGenerator
private string EmitConvertFloat(ConvertFloatNode convertFloatNode) private string EmitConvertFloat(ConvertFloatNode convertFloatNode)
{ {
throw new NotImplementedException(); var value = EmitExpression(convertFloatNode.Value);
return $"({MapType(convertFloatNode.Type)}){value}";
} }
private string EmitConvertInt(ConvertIntNode convertIntNode) private string EmitConvertInt(ConvertIntNode convertIntNode)
{ {
throw new NotImplementedException(); var value = EmitExpression(convertIntNode.Value);
return $"({MapType(convertIntNode.Type)}){value}";
} }
private string EmitCStringLiteral(CStringLiteralNode cStringLiteralNode) private string EmitCStringLiteral(CStringLiteralNode cStringLiteralNode)
@@ -381,22 +417,36 @@ public class CGenerator
private string EmitDereference(DereferenceNode dereferenceNode) private string EmitDereference(DereferenceNode dereferenceNode)
{ {
throw new NotImplementedException(); var pointer = EmitExpression(dereferenceNode.Target);
return $"*({MapType(dereferenceNode.Type)}*){pointer}";
} }
private string EmitFloat32Literal(Float32LiteralNode float32LiteralNode) private string EmitFloat32Literal(Float32LiteralNode float32LiteralNode)
{ {
throw new NotImplementedException(); var str = float32LiteralNode.Value.ToString("G9", System.Globalization.CultureInfo.InvariantCulture);
if (!str.Contains('.') && !str.Contains('e') && !str.Contains('E'))
{
str += ".0";
}
return str + "f";
} }
private string EmitFloat64Literal(Float64LiteralNode float64LiteralNode) private string EmitFloat64Literal(Float64LiteralNode float64LiteralNode)
{ {
throw new NotImplementedException(); var str = float64LiteralNode.Value.ToString("G17", System.Globalization.CultureInfo.InvariantCulture);
if (!str.Contains('.') && !str.Contains('e') && !str.Contains('E'))
{
str += ".0";
}
return str;
} }
private string EmitFloatToIntBuiltin(FloatToIntBuiltinNode floatToIntBuiltinNode) private string EmitFloatToIntBuiltin(FloatToIntBuiltinNode floatToIntBuiltinNode)
{ {
throw new NotImplementedException(); var value = EmitExpression(floatToIntBuiltinNode.Value);
return $"({MapType(floatToIntBuiltinNode.Type)}){value}";
} }
private string EmitFuncCall(FuncCallNode funcCallNode) private string EmitFuncCall(FuncCallNode funcCallNode)
@@ -426,22 +476,23 @@ public class CGenerator
private string EmitAddressOf(AddressOfNode addressOfNode) private string EmitAddressOf(AddressOfNode addressOfNode)
{ {
throw new NotImplementedException(); var value = EmitExpression(addressOfNode.LValue);
return $"(uintptr_t)&{value}";
} }
private string EmitLValueIdentifier(LValueIdentifierNode lValueIdentifierNode) private string EmitLValueIdentifier(LValueIdentifierNode lValueIdentifierNode)
{ {
throw new NotImplementedException(); return lValueIdentifierNode.Name;
} }
private string EmitRValueIdentifier(RValueIdentifierNode rValueIdentifierNode) private string EmitRValueIdentifier(RValueIdentifierNode rValueIdentifierNode)
{ {
throw new NotImplementedException(); return rValueIdentifierNode.Name;
} }
private string EmitSizeBuiltin(SizeBuiltinNode sizeBuiltinNode) private string EmitSizeBuiltin(SizeBuiltinNode sizeBuiltinNode)
{ {
throw new NotImplementedException(); return $"sizeof({MapType(sizeBuiltinNode.TargetType)})";
} }
private string EmitStringLiteral(StringLiteralNode stringLiteralNode) private string EmitStringLiteral(StringLiteralNode stringLiteralNode)
@@ -451,7 +502,8 @@ public class CGenerator
private string EmitStructFieldAccess(StructFieldAccessNode structFieldAccessNode) private string EmitStructFieldAccess(StructFieldAccessNode structFieldAccessNode)
{ {
throw new NotImplementedException(); var structExpr = EmitExpression(structFieldAccessNode.Target);
return $"{structExpr}.{structFieldAccessNode.Field}";
} }
private string EmitStructFuncCall(StructFuncCallNode structFuncCallNode) private string EmitStructFuncCall(StructFuncCallNode structFuncCallNode)
@@ -474,7 +526,7 @@ public class CGenerator
? "0" ? "0"
: string.Join(", ", initValues); : string.Join(", ", initValues);
return $"({MapType(structInitializerNode.Type)}){{ {initString} }}"; return $"({MapType(structInitializerNode.Type)}){{{initString}}}";
} }
private string EmitUIntLiteral(UIntLiteralNode uIntLiteralNode) private string EmitUIntLiteral(UIntLiteralNode uIntLiteralNode)

View File

@@ -2,7 +2,7 @@ using System.Text;
namespace NubLang.Generation; namespace NubLang.Generation;
internal class CWriter internal class IndentedTextWriter
{ {
private readonly StringBuilder _builder = new(); private readonly StringBuilder _builder = new();
private int _indentLevel; private int _indentLevel;
@@ -52,10 +52,10 @@ internal class CWriter
private class IndentScope : IDisposable private class IndentScope : IDisposable
{ {
private readonly CWriter _writer; private readonly IndentedTextWriter _writer;
private bool _disposed; private bool _disposed;
public IndentScope(CWriter writer) public IndentScope(IndentedTextWriter writer)
{ {
_writer = writer; _writer = writer;
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,39 +0,0 @@
using System.Text;
namespace NubLang.Generation;
internal class QBEWriter
{
private readonly StringBuilder _builder = new();
public void Indented(string value)
{
_builder.Append('\t');
_builder.AppendLine(value);
}
public void Comment(string comment)
{
_builder.AppendLine("# " + comment);
}
public void WriteLine(string text)
{
_builder.AppendLine(text);
}
public void Write(string text)
{
_builder.Append(text);
}
public void NewLine()
{
_builder.AppendLine();
}
public override string ToString()
{
return _builder.ToString();
}
}

View File

@@ -1,7 +1,7 @@
NUBC = ../../compiler/NubLang.CLI/bin/Debug/net9.0/nubc NUBC = ../../compiler/NubLang.CLI/bin/Debug/net9.0/nubc
out: .build/out.o out: .build/out.o
gcc -nostartfiles -lm -o out x86_64.s .build/out.o raylib-5.5_linux_amd64/lib/libraylib.a clang -nostartfiles -lm -O3 -o out x86_64.s .build/out.o raylib-5.5_linux_amd64/lib/libraylib.a
.build/out.o: $(NUBC) main.nub raylib.nub .build/out.o: $(NUBC) main.nub raylib.nub
$(NUBC) main.nub raylib.nub $(NUBC) main.nub raylib.nub