...
This commit is contained in:
8
example/compile.sh
Executable file
8
example/compile.sh
Executable file
@@ -0,0 +1,8 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
object_files=$(dotnet run --project ../src/compiler/CLI/CLI.csproj src/main.nub src/c.nub)
|
||||||
|
|
||||||
|
echo $object_files
|
||||||
|
|
||||||
|
mkdir -p bin
|
||||||
|
gcc -o bin/out $object_files
|
||||||
BIN
example/lib/libruntime_x64.a
Normal file
BIN
example/lib/libruntime_x64.a
Normal file
Binary file not shown.
@@ -1,43 +0,0 @@
|
|||||||
namespace main
|
|
||||||
|
|
||||||
struct Human {
|
|
||||||
name: cstring
|
|
||||||
}
|
|
||||||
|
|
||||||
export func main(args: []cstring): i64 {
|
|
||||||
// let human: Human
|
|
||||||
|
|
||||||
// human = alloc Human {
|
|
||||||
// name = "member"
|
|
||||||
// }
|
|
||||||
|
|
||||||
// c::puts(human.name)
|
|
||||||
|
|
||||||
// c::puts("literal")
|
|
||||||
|
|
||||||
// let x: cstring
|
|
||||||
|
|
||||||
// x = "variable"
|
|
||||||
|
|
||||||
// c::puts(x)
|
|
||||||
|
|
||||||
// let y: func(cstring)
|
|
||||||
|
|
||||||
// y = c::puts
|
|
||||||
|
|
||||||
// y("proxy")
|
|
||||||
|
|
||||||
// func(){ c::puts("anon") }()
|
|
||||||
|
|
||||||
// let z: func()
|
|
||||||
|
|
||||||
// z = func() { c::puts("anon variable") }
|
|
||||||
|
|
||||||
// z()
|
|
||||||
|
|
||||||
c::printf("%d\n", "test".count)
|
|
||||||
|
|
||||||
// c::puts("test")
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
6
example/src/main.nub
Normal file
6
example/src/main.nub
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
namespace main
|
||||||
|
|
||||||
|
export func main(args: []cstring): i64 {
|
||||||
|
c::puts("test")
|
||||||
|
return 0
|
||||||
|
}
|
||||||
4
run.sh
4
run.sh
@@ -1,4 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
dotnet run --project src/compiler/CLI/CLI.csproj example/main.nub example/c.nub
|
|
||||||
./bin/out
|
|
||||||
@@ -1,6 +1,29 @@
|
|||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
namespace CLI;
|
namespace CLI;
|
||||||
|
|
||||||
public class AR
|
public static class AR
|
||||||
{
|
{
|
||||||
|
public static async Task<bool> Invoke(string fileName, 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("ar error when archiving:\n" + errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
return process.ExitCode == 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<AssemblyName>nub</AssemblyName>
|
<AssemblyName>nubc</AssemblyName>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>net9.0</TargetFramework>
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
@@ -14,13 +14,8 @@
|
|||||||
<ProjectReference Include="..\Syntax\Syntax.csproj" />
|
<ProjectReference Include="..\Syntax\Syntax.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Folder Include="runtime\" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Remove="runtime\libruntime_x64.a" />
|
<None Remove="runtime\libruntime_x64.a" />
|
||||||
<EmbeddedResource Include="runtime\libruntime_x64.a" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -4,49 +4,37 @@ namespace CLI;
|
|||||||
|
|
||||||
public static class GCC
|
public static class GCC
|
||||||
{
|
{
|
||||||
public static async Task<bool> Assemble(string asmPath, string objPath)
|
public static async Task<bool> Assemble(string asm, string objPath)
|
||||||
{
|
{
|
||||||
using var gccProcess = new Process();
|
var dir = Path.GetDirectoryName(objPath);
|
||||||
gccProcess.StartInfo = new ProcessStartInfo("gcc", ["-g", "-nostdlib", "-ffreestanding", "-c", asmPath, "-o", objPath])
|
if (dir != null)
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
using var process = new Process();
|
||||||
|
process.StartInfo = new ProcessStartInfo("gcc", ["-g", "-xassembler", "-c", "-o", objPath, "-"])
|
||||||
{
|
{
|
||||||
UseShellExecute = false,
|
UseShellExecute = false,
|
||||||
|
RedirectStandardInput = true,
|
||||||
RedirectStandardOutput = true,
|
RedirectStandardOutput = true,
|
||||||
RedirectStandardError = true,
|
RedirectStandardError = true,
|
||||||
CreateNoWindow = true
|
CreateNoWindow = true
|
||||||
};
|
};
|
||||||
|
|
||||||
gccProcess.Start();
|
process.Start();
|
||||||
await gccProcess.WaitForExitAsync();
|
|
||||||
|
|
||||||
var gccErrors = await gccProcess.StandardError.ReadToEndAsync();
|
await process.StandardInput.WriteAsync(asm);
|
||||||
if (!string.IsNullOrWhiteSpace(gccErrors))
|
process.StandardInput.Close();
|
||||||
|
|
||||||
|
await process.WaitForExitAsync();
|
||||||
|
|
||||||
|
var errors = await process.StandardError.ReadToEndAsync();
|
||||||
|
if (!string.IsNullOrWhiteSpace(errors))
|
||||||
{
|
{
|
||||||
await Console.Error.WriteLineAsync("gcc error when assembling:\n" + gccErrors);
|
await Console.Error.WriteLineAsync("gcc error when assembling:\n" + errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
return gccProcess.ExitCode == 0;
|
return process.ExitCode == 0;
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task<bool> Link(List<string> objectFiles, string outputPath)
|
|
||||||
{
|
|
||||||
using var gccProcess = new Process();
|
|
||||||
gccProcess.StartInfo = new ProcessStartInfo("gcc", ["-g", "-nostdlib", "-ffreestanding", "-o", outputPath, ..objectFiles])
|
|
||||||
{
|
|
||||||
UseShellExecute = false,
|
|
||||||
RedirectStandardOutput = true,
|
|
||||||
RedirectStandardError = true,
|
|
||||||
CreateNoWindow = true
|
|
||||||
};
|
|
||||||
|
|
||||||
gccProcess.Start();
|
|
||||||
await gccProcess.WaitForExitAsync();
|
|
||||||
|
|
||||||
var gccErrors = await gccProcess.StandardError.ReadToEndAsync();
|
|
||||||
if (!string.IsNullOrWhiteSpace(gccErrors))
|
|
||||||
{
|
|
||||||
await Console.Error.WriteLineAsync("gcc error when linking:\n" + gccErrors);
|
|
||||||
}
|
|
||||||
|
|
||||||
return gccProcess.ExitCode == 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
using System.Diagnostics;
|
using CLI;
|
||||||
using System.Reflection;
|
|
||||||
using CLI;
|
|
||||||
using Generation.QBE;
|
using Generation.QBE;
|
||||||
using Syntax;
|
using Syntax;
|
||||||
using Syntax.Diagnostics;
|
using Syntax.Diagnostics;
|
||||||
@@ -9,40 +7,22 @@ using Syntax.Tokenization;
|
|||||||
using Syntax.Typing;
|
using Syntax.Typing;
|
||||||
using Binder = Syntax.Typing.Binder;
|
using Binder = Syntax.Typing.Binder;
|
||||||
|
|
||||||
const string BIN_DIR = "bin";
|
const string OUT_DIR = "bin-int";
|
||||||
const string BIN_INT_DIR = "bin-int";
|
|
||||||
|
|
||||||
if (Directory.Exists(BIN_DIR))
|
if (Directory.Exists(OUT_DIR))
|
||||||
{
|
{
|
||||||
Directory.Delete(BIN_DIR, true);
|
Directory.Delete(OUT_DIR, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Directory.Exists(BIN_INT_DIR))
|
|
||||||
{
|
|
||||||
Directory.Delete(BIN_INT_DIR, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
Directory.CreateDirectory(BIN_DIR);
|
|
||||||
Directory.CreateDirectory(BIN_INT_DIR);
|
|
||||||
|
|
||||||
var files = new List<string>();
|
var files = new List<string>();
|
||||||
|
|
||||||
string? runtimePath = null;
|
|
||||||
|
|
||||||
foreach (var arg in args)
|
foreach (var arg in args)
|
||||||
{
|
{
|
||||||
if (arg.StartsWith("-r="))
|
files.Add(arg);
|
||||||
{
|
|
||||||
runtimePath = arg.Substring("-r=".Length);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
files.Add(arg);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var diagnostics = new List<Diagnostic>();
|
var diagnostics = new List<Diagnostic>();
|
||||||
var syntaxTrees = new List<SyntaxTree>();
|
var syntaxTrees = new Dictionary<string, SyntaxTree>();
|
||||||
|
|
||||||
foreach (var file in files)
|
foreach (var file in files)
|
||||||
{
|
{
|
||||||
@@ -61,29 +41,27 @@ foreach (var file in files)
|
|||||||
var tokenizeResult = Tokenizer.Tokenize(sourceText, out var tokenizerDiagnostics);
|
var tokenizeResult = Tokenizer.Tokenize(sourceText, out var tokenizerDiagnostics);
|
||||||
diagnostics.AddRange(tokenizerDiagnostics);
|
diagnostics.AddRange(tokenizerDiagnostics);
|
||||||
|
|
||||||
var syntaxTree = Parser.ParseFile(tokenizeResult, file, out var parseDiagnostics);
|
var syntaxTree = Parser.ParseFile(tokenizeResult, out var parseDiagnostics);
|
||||||
diagnostics.AddRange(parseDiagnostics);
|
diagnostics.AddRange(parseDiagnostics);
|
||||||
|
|
||||||
if (syntaxTree != null)
|
if (syntaxTree != null)
|
||||||
{
|
{
|
||||||
syntaxTrees.Add(syntaxTree);
|
syntaxTrees[file] = syntaxTree;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new Exception();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var definitionTable = new DefinitionTable(syntaxTrees);
|
var definitionTable = new DefinitionTable(syntaxTrees.Values);
|
||||||
|
|
||||||
var boundSyntaxTrees = new List<BoundSyntaxTree>();
|
var boundSyntaxTrees = new Dictionary<string, BoundSyntaxTree>();
|
||||||
|
|
||||||
foreach (var syntaxTree in syntaxTrees)
|
foreach (var (file, syntaxTree) in syntaxTrees)
|
||||||
{
|
{
|
||||||
boundSyntaxTrees.Add(Binder.Bind(syntaxTree, definitionTable));
|
var boundSyntaxTree = Binder.Bind(syntaxTree, definitionTable, out var binderDiagnostics);
|
||||||
|
diagnostics.AddRange(binderDiagnostics);
|
||||||
|
boundSyntaxTrees[file] = boundSyntaxTree;
|
||||||
}
|
}
|
||||||
|
|
||||||
var boundDefinitionTable = new BoundDefinitionTable(boundSyntaxTrees);
|
var boundDefinitionTable = new BoundDefinitionTable(boundSyntaxTrees.Values);
|
||||||
|
|
||||||
foreach (var diagnostic in diagnostics)
|
foreach (var diagnostic in diagnostics)
|
||||||
{
|
{
|
||||||
@@ -97,48 +75,18 @@ if (diagnostics.Any(diagnostic => diagnostic.Severity == DiagnosticSeverity.Erro
|
|||||||
|
|
||||||
var objectFiles = new List<string>();
|
var objectFiles = new List<string>();
|
||||||
|
|
||||||
if (runtimePath == null)
|
foreach (var file in files)
|
||||||
{
|
{
|
||||||
const string RUNTIME_NAME = "libruntime_x64";
|
var ssa = QBEGenerator.Emit(boundSyntaxTrees[file], boundDefinitionTable);
|
||||||
await using var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(RUNTIME_NAME);
|
|
||||||
if (stream == null)
|
|
||||||
{
|
|
||||||
throw new Exception("Runtime stream is null");
|
|
||||||
}
|
|
||||||
|
|
||||||
var tmpDir = Directory.CreateTempSubdirectory("nub");
|
|
||||||
runtimePath = Path.Combine(tmpDir.FullName, RUNTIME_NAME + ".a");
|
|
||||||
|
|
||||||
await using var writer = new FileStream(runtimePath, FileMode.Create, FileAccess.Write);
|
|
||||||
await stream.CopyToAsync(writer);
|
|
||||||
}
|
|
||||||
|
|
||||||
objectFiles.Add(runtimePath);
|
|
||||||
|
|
||||||
foreach (var boundSyntaxTree in boundSyntaxTrees)
|
|
||||||
{
|
|
||||||
var relativeFilePath = Path.GetRelativePath(Environment.CurrentDirectory, boundSyntaxTree.FilePath);
|
|
||||||
var outputPath = Path.Combine(BIN_INT_DIR, relativeFilePath);
|
|
||||||
|
|
||||||
var outputDirectory = Path.GetDirectoryName(outputPath);
|
|
||||||
Debug.Assert(!string.IsNullOrWhiteSpace(outputDirectory));
|
|
||||||
Directory.CreateDirectory(outputDirectory);
|
|
||||||
|
|
||||||
var ssa = QBEGenerator.Emit(boundSyntaxTree, boundDefinitionTable);
|
|
||||||
var ssaPath = Path.ChangeExtension(outputPath, "ssa");
|
|
||||||
File.WriteAllText(ssaPath, ssa);
|
|
||||||
|
|
||||||
var asm = await QBE.Invoke(ssa);
|
var asm = await QBE.Invoke(ssa);
|
||||||
if (asm == null)
|
if (asm == null)
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
var asmPath = Path.ChangeExtension(outputPath, "s");
|
var fileName = $"{Path.GetFileNameWithoutExtension(file)}_{StringRandomizer.GenerateUniqueHexString(8)}.o";
|
||||||
await File.WriteAllTextAsync(asmPath, asm);
|
var objPath = Path.Combine(OUT_DIR, fileName);
|
||||||
|
var asmSuccess = await GCC.Assemble(asm, objPath);
|
||||||
var objPath = Path.ChangeExtension(outputPath, "o");
|
|
||||||
var asmSuccess = await GCC.Assemble(asmPath, objPath);
|
|
||||||
if (!asmSuccess)
|
if (!asmSuccess)
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
@@ -147,5 +95,28 @@ foreach (var boundSyntaxTree in boundSyntaxTrees)
|
|||||||
objectFiles.Add(objPath);
|
objectFiles.Add(objPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
var linkSuccess = await GCC.Link(objectFiles, Path.Combine(BIN_DIR, "out"));
|
foreach (var objectFile in objectFiles)
|
||||||
return linkSuccess ? 0 : 1;
|
{
|
||||||
|
Console.Out.WriteLine(objectFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
internal static class StringRandomizer
|
||||||
|
{
|
||||||
|
private static readonly char[] StringChars = "0123456789abcdef".ToArray();
|
||||||
|
|
||||||
|
public static string GenerateUniqueHexString(int length)
|
||||||
|
{
|
||||||
|
var rand = new Random();
|
||||||
|
var hexString = "";
|
||||||
|
|
||||||
|
for (var i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
var randIndex = rand.Next(0, StringChars.Length);
|
||||||
|
hexString += StringChars[randIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
return hexString;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,8 +6,8 @@ public static class QBE
|
|||||||
{
|
{
|
||||||
public static async Task<string?> Invoke(string ssa)
|
public static async Task<string?> Invoke(string ssa)
|
||||||
{
|
{
|
||||||
using var qbeProcess = new Process();
|
using var process = new Process();
|
||||||
qbeProcess.StartInfo = new ProcessStartInfo
|
process.StartInfo = new ProcessStartInfo
|
||||||
{
|
{
|
||||||
FileName = "qbe",
|
FileName = "qbe",
|
||||||
UseShellExecute = false,
|
UseShellExecute = false,
|
||||||
@@ -17,21 +17,21 @@ public static class QBE
|
|||||||
CreateNoWindow = true
|
CreateNoWindow = true
|
||||||
};
|
};
|
||||||
|
|
||||||
qbeProcess.Start();
|
process.Start();
|
||||||
|
|
||||||
await qbeProcess.StandardInput.WriteAsync(ssa);
|
await process.StandardInput.WriteAsync(ssa);
|
||||||
qbeProcess.StandardInput.Close();
|
process.StandardInput.Close();
|
||||||
|
|
||||||
await qbeProcess.WaitForExitAsync();
|
await process.WaitForExitAsync();
|
||||||
|
|
||||||
var qbeErrors = await qbeProcess.StandardError.ReadToEndAsync();
|
var errors = await process.StandardError.ReadToEndAsync();
|
||||||
if (!string.IsNullOrWhiteSpace(qbeErrors))
|
if (!string.IsNullOrWhiteSpace(errors))
|
||||||
{
|
{
|
||||||
await Console.Error.WriteLineAsync("qbe error:\n" + qbeErrors);
|
await Console.Error.WriteLineAsync("qbe error:\n" + errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
var asm = await qbeProcess.StandardOutput.ReadToEndAsync();
|
var asm = await process.StandardOutput.ReadToEndAsync();
|
||||||
|
|
||||||
return qbeProcess.ExitCode == 0 ? asm : null;
|
return process.ExitCode == 0 ? asm : null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ public static class Parser
|
|||||||
private static IEnumerable<Token> _tokens = [];
|
private static IEnumerable<Token> _tokens = [];
|
||||||
private static int _index;
|
private static int _index;
|
||||||
|
|
||||||
public static SyntaxTree? ParseFile(IEnumerable<Token> tokens, string filePath, out IEnumerable<Diagnostic> diagnostics)
|
public static SyntaxTree? ParseFile(IEnumerable<Token> tokens, out IEnumerable<Diagnostic> diagnostics)
|
||||||
{
|
{
|
||||||
_tokens = tokens;
|
_tokens = tokens;
|
||||||
_namespace = null!;
|
_namespace = null!;
|
||||||
@@ -46,7 +46,7 @@ public static class Parser
|
|||||||
}
|
}
|
||||||
|
|
||||||
diagnostics = _diagnostics;
|
diagnostics = _diagnostics;
|
||||||
return new SyntaxTree(filePath, _namespace, definitions);
|
return new SyntaxTree(_namespace, definitions);
|
||||||
}
|
}
|
||||||
catch (ParseException ex)
|
catch (ParseException ex)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,4 +2,4 @@
|
|||||||
|
|
||||||
namespace Syntax.Parsing;
|
namespace Syntax.Parsing;
|
||||||
|
|
||||||
public record SyntaxTree(string FilePath, string Namespace, List<DefinitionNode> Definitions);
|
public record SyntaxTree(string Namespace, List<DefinitionNode> Definitions);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Common;
|
using Common;
|
||||||
|
using Syntax.Diagnostics;
|
||||||
using Syntax.Parsing;
|
using Syntax.Parsing;
|
||||||
using Syntax.Parsing.Node;
|
using Syntax.Parsing.Node;
|
||||||
using Syntax.Tokenization;
|
using Syntax.Tokenization;
|
||||||
@@ -16,7 +17,7 @@ public static class Binder
|
|||||||
private static Dictionary<string, NubType> _variables = new();
|
private static Dictionary<string, NubType> _variables = new();
|
||||||
private static NubType? _funcReturnType;
|
private static NubType? _funcReturnType;
|
||||||
|
|
||||||
public static BoundSyntaxTree Bind(SyntaxTree syntaxTree, DefinitionTable definitionTable)
|
public static BoundSyntaxTree Bind(SyntaxTree syntaxTree, DefinitionTable definitionTable, out IEnumerable<Diagnostic> diagnostics)
|
||||||
{
|
{
|
||||||
_syntaxTree = syntaxTree;
|
_syntaxTree = syntaxTree;
|
||||||
_definitionTable = definitionTable;
|
_definitionTable = definitionTable;
|
||||||
@@ -31,7 +32,8 @@ public static class Binder
|
|||||||
definitions.Add(BindDefinition(definition));
|
definitions.Add(BindDefinition(definition));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new BoundSyntaxTree(syntaxTree.FilePath, syntaxTree.Namespace, definitions);
|
diagnostics = [];
|
||||||
|
return new BoundSyntaxTree(syntaxTree.Namespace, definitions);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static BoundDefinitionNode BindDefinition(DefinitionNode node)
|
private static BoundDefinitionNode BindDefinition(DefinitionNode node)
|
||||||
|
|||||||
@@ -2,4 +2,4 @@
|
|||||||
|
|
||||||
namespace Syntax.Typing;
|
namespace Syntax.Typing;
|
||||||
|
|
||||||
public record BoundSyntaxTree(string FilePath, string Namespace, List<BoundDefinitionNode> Definitions);
|
public record BoundSyntaxTree(string Namespace, List<BoundDefinitionNode> Definitions);
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ PointerAlignment: Left
|
|||||||
AllowShortFunctionsOnASingleLine: None
|
AllowShortFunctionsOnASingleLine: None
|
||||||
|
|
||||||
# Control how short statements are placed
|
# Control how short statements are placed
|
||||||
AllowShortBlocksOnASingleLine: Empty
|
AllowShortBlocksOnASingleLine: Never
|
||||||
AllowShortIfStatementsOnASingleLine: Never
|
AllowShortIfStatementsOnASingleLine: Never
|
||||||
AllowShortLoopsOnASingleLine: false
|
AllowShortLoopsOnASingleLine: false
|
||||||
|
|
||||||
|
|||||||
4
src/runtime/.gitignore
vendored
4
src/runtime/.gitignore
vendored
@@ -1,2 +1,2 @@
|
|||||||
out
|
bin
|
||||||
out-int
|
bin-int
|
||||||
@@ -1,16 +1,16 @@
|
|||||||
CC ?= x86_64-linux-gnu-gcc
|
CC ?= x86_64-linux-gnu-gcc
|
||||||
TARGET ?= x64
|
TARGET ?= x64
|
||||||
|
|
||||||
CFLAGS = -nostdlib -ffreestanding -Wall -Werror -Wextra
|
CFLAGS = -nostdlib -ffreestanding -Wall -Werror -Wextra -g
|
||||||
|
|
||||||
libruntime: out-int/runtime.o
|
libruntime: bin-int/runtime.o
|
||||||
$(CC) $(CFLAGS) -c targets/$(TARGET).s -o out-int/$(TARGET).o
|
$(CC) $(CFLAGS) -c targets/$(TARGET).s -o bin-int/$(TARGET).o
|
||||||
mkdir -p out
|
mkdir -p bin
|
||||||
ar rcs out/libruntime_$(TARGET).a out-int/runtime.o out-int/$(TARGET).o
|
ar rcs bin/libruntime_$(TARGET).a bin-int/runtime.o bin-int/$(TARGET).o
|
||||||
|
|
||||||
out-int/runtime.o: runtime/runtime.c
|
bin-int/runtime.o: runtime/runtime.c
|
||||||
mkdir -p out-int
|
mkdir -p bin-int
|
||||||
$(CC) $(CFLAGS) -c runtime/runtime.c -o out-int/runtime.o
|
$(CC) $(CFLAGS) -c runtime/runtime.c -o bin-int/runtime.o
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -r out out-int
|
rm -r bin bin-int
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#define NUB_PANIC_ERROR_CODE 101
|
typedef struct nub_string {
|
||||||
|
uint64_t size;
|
||||||
extern void nub_write_string(const char* str);
|
uint8_t buffer[];
|
||||||
extern void nub_exit(int code);
|
} nub_string_t;
|
||||||
|
|
||||||
uint64_t nub_cstring_length(const char* string)
|
uint64_t nub_cstring_length(const char* string)
|
||||||
{
|
{
|
||||||
@@ -14,9 +14,22 @@ uint64_t nub_cstring_length(const char* string)
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t nub_string_length()
|
uint64_t nub_string_length(const nub_string_t* string)
|
||||||
{
|
{
|
||||||
return 0;
|
uint64_t count = 0;
|
||||||
|
uint64_t i = 0;
|
||||||
|
|
||||||
|
while (i < string->size) {
|
||||||
|
uint8_t byte = string->buffer[i];
|
||||||
|
|
||||||
|
if ((byte & 0b11000000) != 0b10000000) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nub_memcpy(uint8_t* source, uint8_t* destination, uint64_t length)
|
void nub_memcpy(uint8_t* source, uint8_t* destination, uint64_t length)
|
||||||
@@ -32,24 +45,3 @@ void nub_memset(uint8_t* destination, uint8_t value, uint64_t count)
|
|||||||
destination[i] = value;
|
destination[i] = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void nub_panic_array_oob()
|
|
||||||
{
|
|
||||||
nub_write_string("Array out of bounds\n");
|
|
||||||
nub_exit(NUB_PANIC_ERROR_CODE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void nub_panic_oom()
|
|
||||||
{
|
|
||||||
nub_write_string("Out of memory\n");
|
|
||||||
nub_exit(NUB_PANIC_ERROR_CODE);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern uint64_t main();
|
|
||||||
|
|
||||||
__attribute__((noreturn)) void _start()
|
|
||||||
{
|
|
||||||
uint64_t exit_code = main();
|
|
||||||
nub_exit(exit_code);
|
|
||||||
__builtin_unreachable();
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,20 +1,9 @@
|
|||||||
.intel_syntax noprefix
|
.intel_syntax noprefix
|
||||||
|
|
||||||
.text
|
.text
|
||||||
.globl nub_write_string
|
.globl _start
|
||||||
# void nub_write_string(const char* str)
|
_start:
|
||||||
nub_write_string:
|
mov rdi, rsp
|
||||||
push rdi
|
call main
|
||||||
call nub_cstring_length
|
|
||||||
mov rdx, rax
|
|
||||||
pop rsi
|
|
||||||
mov rax, 1
|
|
||||||
mov rdi, 1
|
|
||||||
syscall
|
|
||||||
|
|
||||||
.text
|
|
||||||
.globl nub_exit
|
|
||||||
# void nub_exit(int code)
|
|
||||||
nub_exit:
|
|
||||||
mov rax, 60
|
mov rax, 60
|
||||||
syscall
|
syscall
|
||||||
|
|||||||
Reference in New Issue
Block a user