| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171 |
- using System.Collections.Concurrent;
- using System.Runtime.CompilerServices;
- using Lua.Internal;
- using Lua.Runtime;
- namespace Lua.CodeAnalysis.Compilation;
- public class ScopeCompilationContext : IDisposable
- {
- static class Pool
- {
- static ConcurrentStack<ScopeCompilationContext> stack = new();
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static ScopeCompilationContext Rent()
- {
- if (!stack.TryPop(out var context))
- {
- context = new();
- }
- return context;
- }
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static void Return(ScopeCompilationContext context)
- {
- context.Reset();
- stack.Push(context);
- }
- }
- readonly Dictionary<ReadOnlyMemory<char>, LocalVariableDescription> localVariables = new(256, Utf16StringMemoryComparer.Default);
- readonly Dictionary<ReadOnlyMemory<char>, LabelDescription> labels = new(32, Utf16StringMemoryComparer.Default);
- public byte StackStartPosition { get; private set; }
- public byte StackPosition { get; set; }
- public byte StackTopPosition
- {
- get => (byte)(StackPosition - 1);
- }
- public bool HasCapturedLocalVariables { get; internal set; }
- /// <summary>
- /// Function context
- /// </summary>
- public FunctionCompilationContext Function { get; internal set; } = default!;
- /// <summary>
- /// Parent scope context
- /// </summary>
- public ScopeCompilationContext? Parent { get; private set; }
- public ScopeCompilationContext CreateChildScope()
- {
- var childScope = Pool.Rent();
- childScope.Parent = this;
- childScope.Function = Function;
- childScope.StackStartPosition = StackPosition;
- childScope.StackPosition = StackPosition;
- return childScope;
- }
- public FunctionCompilationContext CreateChildFunction()
- {
- var context = FunctionCompilationContext.Create(this);
- return context;
- }
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void PushInstruction(in Instruction instruction, SourcePosition position, bool incrementStackPosition = false)
- {
- Function.PushInstruction(instruction, position);
- if (incrementStackPosition) StackPosition++;
- Function.MaxStackPosition = Math.Max(Function.MaxStackPosition, StackPosition);
- }
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void TryPushCloseUpValue(byte top, SourcePosition position)
- {
- if (HasCapturedLocalVariables && top != 0)
- {
- Function.PushInstruction(Instruction.Jmp(top, 0), position);
- }
- }
- /// <summary>
- /// Add new local variable.
- /// </summary>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void AddLocalVariable(ReadOnlyMemory<char> name, LocalVariableDescription description)
- {
- localVariables[name] = description;
- }
- /// <summary>
- /// Gets the local variable in scope.
- /// </summary>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool TryGetLocalVariable(ReadOnlyMemory<char> name, out LocalVariableDescription description)
- {
- if (localVariables.TryGetValue(name, out description)) return true;
- // Find local variables defined in the same function
- if (Parent != null)
- {
- return Parent.TryGetLocalVariable(name, out description);
- }
- return false;
- }
- /// <summary>
- /// Gets the local variable in this scope.
- /// </summary>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool TryGetLocalVariableInThisScope(ReadOnlyMemory<char> name, out LocalVariableDescription description)
- {
- return localVariables.TryGetValue(name, out description);
- }
- /// <summary>
- /// Add new label.
- /// </summary>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void AddLabel(LabelDescription description)
- {
- labels.Add(description.Name, description);
- }
- /// <summary>
- /// Gets the label in scope.
- /// </summary>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool TryGetLabel(ReadOnlyMemory<char> name, out LabelDescription description)
- {
- if (labels.TryGetValue(name, out description)) return true;
- // Find labels defined in the same function
- if (Parent != null)
- {
- return Parent.TryGetLabel(name, out description);
- }
- return false;
- }
- /// <summary>
- /// Resets the values held in the context.
- /// </summary>
- public void Reset()
- {
- Parent = null;
- StackStartPosition = 0;
- StackPosition = 0;
- HasCapturedLocalVariables = false;
- localVariables.Clear();
- labels.Clear();
- }
- /// <summary>
- /// Returns the context object to the pool.
- /// </summary>
- public void Dispose()
- {
- Function = null!;
- Pool.Return(this);
- }
- }
|