This commit is contained in:
nub31
2025-07-07 18:56:47 +02:00
parent aa8bf71c23
commit 5672d181fe
15 changed files with 155 additions and 150 deletions

View File

@@ -12,14 +12,13 @@ public partial class QBEGenerator
private readonly BoundDefinitionTable _definitionTable;
private readonly QBEWriter _writer;
private List<CStringLiteral> _cStringLiterals = [];
private List<StringLiteral> _stringLiterals = [];
private Stack<string> _breakLabels = [];
private Stack<string> _continueLabels = [];
private Queue<(BoundAnonymousFunc Func, string Name)> _anonymousFunctions = [];
private Dictionary<BoundTraitFuncImpl, string> _implFunctions = [];
private Stack<Variable> _variables = [];
private Stack<int> _variableScopes = [];
private readonly List<CStringLiteral> _cStringLiterals = [];
private readonly List<StringLiteral> _stringLiterals = [];
private readonly Stack<string> _breakLabels = [];
private readonly Stack<string> _continueLabels = [];
private readonly Queue<(BoundAnonymousFunc Func, string Name)> _anonymousFunctions = [];
private readonly Dictionary<BoundTraitFuncImpl, string> _implFunctions = [];
private readonly Stack<Scope> _scopes = [];
private int _tmpIndex;
private int _labelIndex;
private int _anonymousFuncIndex;
@@ -28,6 +27,8 @@ public partial class QBEGenerator
private int _implFuncNameIndex;
private bool _codeIsReachable = true;
private Scope Scope => _scopes.Peek();
public QBEGenerator(BoundSyntaxTree syntaxTree, BoundDefinitionTable definitionTable, string file)
{
_syntaxTree = syntaxTree;
@@ -37,14 +38,13 @@ public partial class QBEGenerator
public string Emit()
{
_cStringLiterals = [];
_stringLiterals = [];
_breakLabels = [];
_continueLabels = [];
_anonymousFunctions = [];
_implFunctions = [];
_variables = [];
_variableScopes = [];
_cStringLiterals.Clear();
_stringLiterals.Clear();
_breakLabels.Clear();
_continueLabels.Clear();
_anonymousFunctions.Clear();
_implFunctions.Clear();
_scopes.Clear();
_tmpIndex = 0;
_labelIndex = 0;
_anonymousFuncIndex = 0;
@@ -347,18 +347,15 @@ public partial class QBEGenerator
return "l";
}
private void EmitFuncDefinition(string name, IEnumerable<BoundFuncParameter> parameters, NubType returnType, BoundBlock body)
private void EmitFuncDefinition(string name, IReadOnlyList<BoundFuncParameter> parameters, NubType returnType, BoundBlock body)
{
var parameterArray = parameters.ToArray();
_variables.Clear();
_variableScopes.Clear();
_labelIndex = 0;
_tmpIndex = 0;
var builder = new StringBuilder();
builder.Append("export function ");
if (returnType is not NubVoidType)
{
builder.Append(FuncQBETypeName(returnType) + ' ');
@@ -366,15 +363,16 @@ public partial class QBEGenerator
builder.Append(name);
var parameterStrings = parameterArray.Select(x => FuncQBETypeName(x.Type) + $" %{x.Name}");
builder.Append($"({string.Join(", ", parameterStrings)})");
builder.Append($"({string.Join(", ", parameters.Select(x => FuncQBETypeName(x.Type) + $" %{x.Name}"))})");
_writer.StartFunction(builder.ToString());
var parameterVars = parameterArray.Select(parameter => new Variable(parameter.Name, new Val("%" + parameter.Name, parameter.Type, ValKind.Direct))).ToList();
var scope = new Scope();
EmitBlock(body, parameterVars);
foreach (var parameter in parameters)
{
scope.Declare(parameter.Name, new Val("%" + parameter.Name, parameter.Type, ValKind.Direct));
}
if (body.Statements.LastOrDefault() is not BoundReturn)
{
@@ -445,6 +443,20 @@ public partial class QBEGenerator
_writer.WriteLine("}");
}
private void EmitBlock(BoundBlock block, Scope? scope = null)
{
_scopes.Push(scope ?? Scope.SubScope());
foreach (var statement in block.Statements.Where(_ => _codeIsReachable))
{
EmitStatement(statement);
}
_scopes.Pop();
_codeIsReachable = true;
}
private string EmitUnwrap(Val val)
{
return val.Kind switch
@@ -525,29 +537,49 @@ public partial class QBEGenerator
#endregion
}
internal class StringLiteral(string value, string name)
public class StringLiteral(string value, string name)
{
public string Value { get; } = value;
public string Name { get; } = name;
}
internal class CStringLiteral(string value, string name)
public class CStringLiteral(string value, string name)
{
public string Value { get; } = value;
public string Name { get; } = name;
}
internal class Variable(string name, Val val)
public record Val(string Name, NubType Type, ValKind Kind, MethodCallContext? FuncCallContext = null);
public class Scope(Scope? parent = null)
{
public string Name { get; } = name;
public Val Val { get; } = val;
private readonly Dictionary<string, Val> _variables = [];
public Val Lookup(string name)
{
var variable = _variables.GetValueOrDefault(name);
if (variable != null)
{
return variable;
}
return parent?.Lookup(name) ?? throw new UnreachableException($"Variable '{name}' not found");
}
public void Declare(string name, Val value)
{
_variables.Add(name, value);
}
public Scope SubScope()
{
return new Scope(this);
}
}
internal record Val(string Name, NubType Type, ValKind Kind, MethodCallContext? FuncCallContext = null);
public record MethodCallContext(Val ThisArg);
internal record MethodCallContext(Val ThisArg);
internal enum ValKind
public enum ValKind
{
Pointer,
Direct,