/
EvilBeaver
/
OneScript
Обзор
Документация
Войти
/
EvilBeaver
/
OneScript
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
v1.8.1
src/ScriptEngine/Compiler/CompilerContext.cs
226 строк
7 KB
Andrei Ovsiankin
Удалены неиспользуемые директивы по проекту
05 янв 2020, 23:29
05 янв 2020, 23:29
4be0088
Код
Авторство
О чём код?
/*---------------------------------------------------------- This Source Code Form is subject to the terms of the Mozilla Public License, v.2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. ----------------------------------------------------------*/ using System; using System.Collections.Generic; using System.Runtime.CompilerServices; using ScriptEngine.Machine; namespace ScriptEngine.Compiler { class CompilerContext : ICompilerContext { readonly List<SymbolScope> _scopeStack = new List<SymbolScope>(); public void PushScope(SymbolScope scope) { _scopeStack.Add(scope); } public SymbolScope PopScope() { var idx = _scopeStack.Count - 1; if (idx >= 0) { var retVal = _scopeStack[idx]; _scopeStack.RemoveAt(idx); return retVal; } else { throw new InvalidOperationException("No scopes defined"); } } public SymbolScope Peek() { var idx = _scopeStack.Count - 1; if (idx >= 0) { return _scopeStack[idx]; } else { throw new InvalidOperationException("No scopes defined"); } } private SymbolBinding GetSymbol(string symbol, Func<SymbolScope, int> extract) { if (TryGetSymbol(symbol, extract, out var result)) { return result; } throw new SymbolNotFoundException(symbol); } private bool TryGetSymbol(string symbol, Func<SymbolScope, int> extract, out SymbolBinding result) { for (int i = _scopeStack.Count - 1; i >= 0; i--) { var number = extract(_scopeStack[i]); if (number < 0) continue; result = new SymbolBinding(); result.CodeIndex = number; result.ContextIndex = i; return true; } result = default(SymbolBinding); return false; } private bool HasSymbol(Func<SymbolScope, bool> definitionCheck) { for (int i = _scopeStack.Count - 1; i >= 0; i--) { var isDefined = definitionCheck(_scopeStack[i]); if (isDefined) return true; } return false; } public VariableBinding GetVariable(string name) { var sb = GetSymbol(name, x => ExtractVariableIndex(name, x)); return new VariableBinding() { type = _scopeStack[sb.ContextIndex].GetVariable(sb.CodeIndex).Type, binding = sb }; } public SymbolBinding GetMethod(string name) { return GetSymbol(name, x => ExtractMethodIndex(name, x)); } public bool TryGetMethod(string name, out SymbolBinding result) { return TryGetSymbol(name, x => ExtractMethodIndex(name, x), out result); } public bool TryGetVariable(string name, out VariableBinding vb) { var hasSymbol = TryGetSymbol(name, x => ExtractVariableIndex(name, x), out var sb); if (!hasSymbol) { vb = default(VariableBinding); return false; } vb = new VariableBinding() { type = _scopeStack[sb.ContextIndex].GetVariable(sb.CodeIndex).Type, binding = sb }; return true; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private int ExtractVariableIndex(string name, SymbolScope scope) { if (scope.IsVarDefined(name)) { return scope.GetVariableNumber(name); } else return -1; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private int ExtractMethodIndex(string name, SymbolScope scope) { if (scope.IsMethodDefined(name)) { return scope.GetMethodNumber(name); } else return -1; } public SymbolScope GetScope(int scopeIndex) { return _scopeStack[scopeIndex]; } public int ScopeIndex(SymbolScope scope) { return _scopeStack.IndexOf(scope); } public SymbolBinding DefineMethod(MethodInfo method) { if (_scopeStack.Count > 0) { if (!HasSymbol(x => x.IsMethodDefined(method.Name))) { var idx = TopIndex(); var num = _scopeStack[TopIndex()].DefineMethod(method); return new SymbolBinding() { ContextIndex = idx, CodeIndex = num }; } else throw new CompilerException("Symbol already defined"); } throw new InvalidOperationException("Scopes are not defined"); } public SymbolBinding DefineVariable(string name, string alias = null) { if (_scopeStack.Count > 0) { var idx = TopIndex(); var scope = GetScope(idx); if (!scope.IsVarDefined(name)) { var num = scope.DefineVariable(name, alias); return new SymbolBinding() { ContextIndex = idx, CodeIndex = num }; } else throw new CompilerException("Symbol already defined"); } throw new InvalidOperationException("Scopes are not defined"); } public SymbolBinding DefineProperty(string name, string alias = null) { if (_scopeStack.Count > 0) { var idx = TopIndex(); var num = _scopeStack[idx].DefineVariable(name, alias, SymbolType.ContextProperty); return new SymbolBinding() { ContextIndex = idx, CodeIndex = num }; } throw new InvalidOperationException("Scopes are not defined"); } public int TopIndex() { return _scopeStack.Count - 1; } } }