...
This commit is contained in:
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user