public static object EvalReturn(RubyScope /*!*/ scope, object returnValue) { RubyBlockScope blockScope; RubyMethodScope methodScope; scope.GetInnerMostBlockOrMethodScope(out blockScope, out methodScope); if (blockScope != null) { Proc proc = blockScope.BlockFlowControl.Proc; if (blockScope.BlockFlowControl.CallerKind == BlockCallerKind.Call && proc.Kind == ProcKind.Lambda) { throw new BlockUnwinder(returnValue, false); } RuntimeFlowControl owner = proc.LocalScope.FlowControlScope; if (owner.IsActiveMethod) { throw new MethodUnwinder(owner, returnValue); } throw new LocalJumpError("unexpected return"); } else { // return from the current method: throw new MethodUnwinder(scope.FlowControlScope, returnValue); } }
public static RubyTopLevelScope/*!*/ CreateMainTopLevelScope(LocalsDictionary/*!*/ locals, Scope/*!*/ globalScope, LanguageContext/*!*/ language, out object self, out RuntimeFlowControl/*!*/ rfc, string dataPath, int dataOffset) { Assert.NotNull(locals, globalScope, language); RubyContext context = (RubyContext)language; RubyGlobalScope rubyGlobalScope = context.InitializeGlobalScope(globalScope, false); RubyTopLevelScope scope = new RubyTopLevelScope(rubyGlobalScope, null, locals); scope.Initialize(new RuntimeFlowControl(), RubyMethodAttributes.PrivateInstance, rubyGlobalScope.MainObject); scope.SetDebugName("top-main"); var objectClass = context.ObjectClass; objectClass.SetConstant("TOPLEVEL_BINDING", new Binding(scope)); if (dataOffset >= 0) { RubyFile dataFile; if (context.DomainManager.Platform.FileExists(dataPath)) { dataFile = new RubyFile(context, dataPath, RubyFileMode.RDONLY); dataFile.Seek(dataOffset, SeekOrigin.Begin); } else { dataFile = null; } objectClass.SetConstant("DATA", dataFile); } self = scope.SelfObject; rfc = scope.RuntimeFlowControl; return scope; }
internal EvalUnwinder(BlockReturnReason reason, RuntimeFlowControl targetFrame, ProcKind sourceProcKind, object returnValue) : base(returnValue) { Reason = reason; _targetFrame = targetFrame; _sourceProcKind = sourceProcKind; }
public static object EvalReturn(RuntimeFlowControl /*!*/ rfc, object returnValue) { // TODO: get from scope: Proc proc = null; BlockParam blockFlowControl = null; if (rfc.InBlock) { if (blockFlowControl.CallerKind == BlockCallerKind.Call && proc.Kind == ProcKind.Lambda) { throw new BlockUnwinder(returnValue, false); } if (proc.Owner.IsActiveMethod) { throw new MethodUnwinder(proc.Owner, returnValue); } throw new LocalJumpError("unexpected return"); } else { // return from the current method: throw new MethodUnwinder(rfc, returnValue); } }
// post-yield break ops: private static void YieldMethodBreak(RuntimeFlowControl rfc, BlockParam /*!*/ yieldedBlockFlowControl, object returnValue) { Assert.NotNull(yieldedBlockFlowControl); // target proc-converter: RuntimeFlowControl targetFrame = yieldedBlockFlowControl.TargetFrame; Debug.Assert(targetFrame != null); if (targetFrame.IsActiveMethod) { // optimize break to the current frame: if (targetFrame == rfc) { return; } else { throw new MethodUnwinder(targetFrame, returnValue); } } else { throw new LocalJumpError("break from proc-closure"); } }
private static void YieldBlockBreak(RuntimeFlowControl rfc, BlockParam /*!*/ ownerBlockFlowControl, BlockParam /*!*/ yieldedBlockFlowControl, object returnValue) { Assert.NotNull(ownerBlockFlowControl, yieldedBlockFlowControl); // target proc-converter: RuntimeFlowControl targetFrame = yieldedBlockFlowControl.TargetFrame; Debug.Assert(targetFrame != null); if (targetFrame.IsActiveMethod) { if (targetFrame == rfc) { // The current primary super-frame is the proc-converter, however we are still in the block frame that needs to be unwound. // Sets the owner's BFC to exit the current block (recursively up to the primary frame). ownerBlockFlowControl.SetFlowControl(BlockReturnReason.Break, targetFrame, yieldedBlockFlowControl.SourceProcKind); return; } else { throw new MethodUnwinder(targetFrame, returnValue); } } else { throw new LocalJumpError("break from proc-closure"); } }
public static object MethodRetry(RuntimeFlowControl/*!*/ rfc, Proc proc) { if (proc != null) { return RetrySingleton; } else { throw new LocalJumpError("retry used out of rescue", rfc); } }
public static RubyTopLevelScope/*!*/ CreateMainTopLevelScope(LocalsDictionary/*!*/ locals, Scope/*!*/ globalScope, LanguageContext/*!*/ language, out object self, out RuntimeFlowControl/*!*/ rfc, string dataPath, int dataOffset) { Assert.NotNull(locals, globalScope, language); GlobalScopeExtension rubyGlobalScope = (GlobalScopeExtension)language.EnsureScopeExtension(globalScope); RubyTopLevelScope scope = new RubyTopLevelScope(rubyGlobalScope, null, locals); scope.Initialize(new RuntimeFlowControl(), RubyMethodAttributes.PrivateInstance, rubyGlobalScope.MainObject); scope.SetDebugName(rubyGlobalScope.IsHosted ? "top-primary-hosted" : "top-primary"); // define TOPLEVEL_BINDING constant: if (!rubyGlobalScope.IsHosted) { var objectClass = rubyGlobalScope.Context.ObjectClass; objectClass.SetConstant("TOPLEVEL_BINDING", new Binding(scope)); if (dataOffset >= 0) { RubyFile dataFile; if (File.Exists(dataPath)) { dataFile = new RubyFile(rubyGlobalScope.Context, dataPath, RubyFileMode.RDONLY); dataFile.Seek(dataOffset, SeekOrigin.Begin); } else { dataFile = null; } objectClass.SetConstant("DATA", dataFile); } } self = scope.SelfObject; rfc = scope.RuntimeFlowControl; return scope; }
public static RuntimeFlowControl /*!*/ CreateRfcForMethod(Proc proc) { var result = new RuntimeFlowControl(); result._activeFlowControlScope = result; result.InitializeRfc(proc); return(result); }
public static RubyTopLevelScope/*!*/ CreateTopLevelScope(LocalsDictionary/*!*/ locals, Scope/*!*/ globalScope, LanguageContext/*!*/ language, out object self, out RuntimeFlowControl/*!*/ rfc) { RubyTopLevelScope scope = CreateTopLevelScopeInternal(locals, globalScope, language); self = scope.SelfObject; rfc = scope.RuntimeFlowControl; return scope; }
internal void SetFlowControl(BlockReturnReason reason, RuntimeFlowControl targetFrame, ProcKind sourceProcKind) { Debug.Assert((reason == BlockReturnReason.Break) == (targetFrame != null)); _returnReason = reason; _targetFrame = targetFrame; _sourceProcKind = sourceProcKind; }
internal void Initialize(RuntimeFlowControl /*!*/ runtimeFlowControl, RubyMethodAttributes methodAttributes, object selfObject) { Assert.NotNull(runtimeFlowControl); _selfObject = selfObject; _runtimeFlowControl = runtimeFlowControl; _methodAttributes = methodAttributes; }
public static RubyModuleScope/*!*/ CreateModuleScope(LocalsDictionary/*!*/ locals, RubyScope/*!*/ parent, RuntimeFlowControl/*!*/ rfc, RubyModule/*!*/ module) { Assert.NotNull(locals, parent, rfc, module); RubyModuleScope scope = new RubyModuleScope(parent, module, false, rfc, module); scope.SetDebugName((module.IsClass ? "class" : "module") + " " + module.Name); scope.Frame = locals; return scope; }
public static object MethodRetry(RuntimeFlowControl /*!*/ rfc, Proc proc) { if (proc != null) { return(RetrySingleton); } else { throw new LocalJumpError("retry used out of rescue", rfc); } }
public static void EvalNext(RuntimeFlowControl /*!*/ rfc, object returnValue) { if (rfc.InLoop || rfc.InBlock) { throw new BlockUnwinder(returnValue, false); // next } else { throw new LocalJumpError("unexpected next"); } }
public static RuntimeFlowControl/*!*/ CreateRfcForMethod(Proc proc) { RuntimeFlowControl result = new RuntimeFlowControl(); result.IsActiveMethod = true; if (proc != null && proc.Kind == ProcKind.Block) { proc.Kind = ProcKind.Proc; proc.Converter = result; } return result; }
public static void EvalRedo(RuntimeFlowControl /*!*/ rfc) { if (rfc.InLoop || rfc.InBlock) { throw new BlockUnwinder(null, true); // redo } else { throw new LocalJumpError("unexpected redo"); } }
public static RuntimeFlowControl /*!*/ CreateRfcForMethod(Proc proc) { RuntimeFlowControl result = new RuntimeFlowControl(); result.IsActiveMethod = true; if (proc != null && proc.Kind == ProcKind.Block) { proc.Kind = ProcKind.Proc; proc.Converter = result; } return(result); }
public static void EvalBreak(RuntimeFlowControl /*!*/ rfc, object returnValue) { // TODO: get from scope: BlockParam blockFlowControl = null; if (rfc.InLoop || rfc.InBlock) { throw new EvalUnwinder(BlockReturnReason.Break, blockFlowControl.Proc.Converter, blockFlowControl.Proc.Kind, returnValue); } else { throw new LocalJumpError("unexpected break"); } }
public static bool MethodYield(RuntimeFlowControl rfc, BlockParam /*!*/ yieldedBlockFlowControl, object returnValue) { Assert.NotNull(yieldedBlockFlowControl); switch (yieldedBlockFlowControl.ReturnReason) { case BlockReturnReason.Retry: // the result that the caller returns should already be RetrySingleton: return(true); case BlockReturnReason.Break: YieldMethodBreak(rfc, yieldedBlockFlowControl, returnValue); return(true); } return(false); }
public static bool CanRescue(RuntimeFlowControl /*!*/ rfc, Exception /*!*/ e) { if (e is StackUnwinder) { return(false); } LocalJumpError lje = e as LocalJumpError; if (lje != null && ReferenceEquals(lje.SkipFrame, rfc)) { return(false); } return(true); }
public static bool MethodYieldRfc(RuntimeFlowControl rfc, BlockParam /*!*/ yieldedBlockFlowControl, object returnValue) { Assert.NotNull(yieldedBlockFlowControl); switch (yieldedBlockFlowControl.ReturnReason) { case BlockReturnReason.Retry: case BlockReturnReason.Return: // The result that the caller returns already is RetrySingleton/MethodUnwinder, // the call-site is with a block (to which we are yielding) and will handle retry/return. return(true); case BlockReturnReason.Break: YieldMethodBreak(rfc, yieldedBlockFlowControl, returnValue); return(true); } return(false); }
public static object BlockReturn(BlockParam /*!*/ blockFlowControl, object returnValue) { Proc proc = blockFlowControl.Proc; if (blockFlowControl.CallerKind == BlockCallerKind.Call && proc.Kind == ProcKind.Lambda) { return(returnValue); } RuntimeFlowControl owner = proc.LocalScope.FlowControlScope; if (owner.IsActiveMethod) { blockFlowControl.ReturnReason = BlockReturnReason.Return; return(new BlockReturnResult(owner, returnValue)); } throw new LocalJumpError("unexpected return"); }
public static RubyTopLevelScope/*!*/ CreateTopLevelHostedScope(LocalsDictionary/*!*/ locals, Scope/*!*/ globalScope, LanguageContext/*!*/ language, out object self, out RuntimeFlowControl/*!*/ rfc) { RubyContext context = (RubyContext)language; RubyGlobalScope rubyGlobalScope = context.InitializeGlobalScope(globalScope, true); // reuse existing top-level scope if available: RubyTopLevelScope scope = rubyGlobalScope.TopLocalScope; if (scope == null) { scope = new RubyTopLevelScope(rubyGlobalScope, null, locals); scope.Initialize(new RuntimeFlowControl(), RubyMethodAttributes.PrivateInstance, rubyGlobalScope.MainObject); scope.SetDebugName("top-level-hosted"); rubyGlobalScope.TopLocalScope = scope; } self = scope.SelfObject; rfc = scope.RuntimeFlowControl; return scope; }
public static BlockParam /*!*/ CreateBfcForLibraryMethod(Proc /*!*/ proc) { Assert.NotNull(proc); bool isProcConverter; if (proc.Kind == ProcKind.Block) { var rfc = new RuntimeFlowControl(); rfc._activeFlowControlScope = rfc; proc.Converter = rfc; proc.Kind = ProcKind.Proc; isProcConverter = true; } else { isProcConverter = false; } return(new BlockParam(proc, BlockCallerKind.Yield, isProcConverter)); }
public static void EvalRetry(RuntimeFlowControl /*!*/ rfc) { // TODO: get from scope: BlockParam blockFlowControl = null; Proc proc = null; if (rfc.InBlock && blockFlowControl.CallerKind != BlockCallerKind.Yield) { throw new LocalJumpError("retry from proc-clause"); } if (rfc.InRescue || rfc.InBlock || proc != null) { throw new EvalUnwinder(BlockReturnReason.Retry, null, blockFlowControl.Proc.Kind, RetrySingleton); } else { throw new LocalJumpError("retry used out of rescue", rfc); } }
public static void MethodNext(RuntimeFlowControl /*!*/ rfc, object returnValue) { throw new LocalJumpError("unexpected next", rfc); }
public static bool MethodYield(RuntimeFlowControl rfc, BlockParam/*!*/ yieldedBlockFlowControl, object returnValue) { Assert.NotNull(yieldedBlockFlowControl); switch (yieldedBlockFlowControl.ReturnReason) { case BlockReturnReason.Retry: // the result that the caller returns should already be RetrySingleton: return true; case BlockReturnReason.Break: YieldMethodBreak(rfc, yieldedBlockFlowControl, returnValue); return true; } return false; }
internal MethodUnwinder(RuntimeFlowControl /*!*/ targetFrame, object returnValue) : base(returnValue) { Assert.NotNull(targetFrame); TargetFrame = targetFrame; }
// top scope: protected RubyScope(RuntimeFlowControl/*!*/ runtimeFlowControl, object selfObject) { _top = (RubyTopLevelScope)this; _parent = null; _selfObject = selfObject; _runtimeFlowControl = runtimeFlowControl; _methodAttributes = RubyMethodAttributes.PrivateInstance; }
private object _lastInputLine; // TODO: per method scope and top level scope, not block scope // top scope: protected RubyClosureScope(RuntimeFlowControl/*!*/ runtimeFlowControl, object selfObject) : base(runtimeFlowControl, selfObject) { }
public static RubyMethodScope/*!*/ CreateMethodScope(LocalsDictionary/*!*/ locals, RubyScope/*!*/ parentScope, RubyModule/*!*/ declaringModule, string/*!*/ definitionName, RuntimeFlowControl/*!*/ rfc, object selfObject, Proc blockParameter, InterpretedFrame interpretedFrame) { RubyMethodScope scope = new RubyMethodScope(parentScope, declaringModule, definitionName, blockParameter, rfc, selfObject); scope.SetDebugName("method " + definitionName + ((blockParameter != null) ? "&" : null)); scope.Frame = locals; scope.InterpretedFrame = interpretedFrame; return scope; }
// other scopes: protected RubyClosureScope(RubyScope/*!*/ parent, RuntimeFlowControl/*!*/ runtimeFlowControl, object selfObject) : base(parent, runtimeFlowControl, selfObject) { }
public static RubyMethodScope/*!*/ CreateMethodScope(LocalsDictionary/*!*/ locals, RubyScope/*!*/ parent, RubyMethodInfo/*!*/ methodDefinition, RuntimeFlowControl/*!*/ rfc, object selfObject, Proc blockParameter) { Assert.NotNull(locals, parent, methodDefinition, rfc); RubyMethodScope scope = new RubyMethodScope(parent, locals, methodDefinition, blockParameter); scope.Initialize(rfc, RubyMethodAttributes.PublicInstance, selfObject); scope.SetDebugName("method " + methodDefinition.DefinitionName + ((blockParameter != null) ? "&" : null) ); return scope; }
private static void YieldBlockBreak(RuntimeFlowControl rfc, BlockParam/*!*/ ownerBlockFlowControl, BlockParam/*!*/ yieldedBlockFlowControl, object returnValue) { Assert.NotNull(ownerBlockFlowControl, yieldedBlockFlowControl); // target proc-converter: RuntimeFlowControl targetFrame = yieldedBlockFlowControl.TargetFrame; Debug.Assert(targetFrame != null); if (targetFrame.IsActiveMethod) { if (targetFrame == rfc) { // The current primary super-frame is the proc-converter, however we are still in the block frame that needs to be unwound. // Sets the owner's BFC to exit the current block (recursively up to the primary frame). ownerBlockFlowControl.SetFlowControl(BlockReturnReason.Break, targetFrame, yieldedBlockFlowControl.SourceProcKind); return; } else { throw new MethodUnwinder(targetFrame, returnValue); } } else { throw new LocalJumpError("break from proc-closure"); } }
internal LocalJumpError(string/*!*/ message, RuntimeFlowControl/*!*/ skipFrame) : this(message, (Exception)null) { Assert.NotNull(message, skipFrame); _skipFrame = skipFrame; }
internal void Initialize(RuntimeFlowControl/*!*/ runtimeFlowControl, RubyMethodAttributes methodAttributes, object selfObject) { Assert.NotNull(runtimeFlowControl); _selfObject = selfObject; _runtimeFlowControl = runtimeFlowControl; _methodAttributes = methodAttributes; }
public static void LeaveMethodFrame(RuntimeFlowControl/*!*/ rfc) { rfc.IsActiveMethod = false; }
// other scopes: protected RubyScope(RubyScope/*!*/ parent, RuntimeFlowControl/*!*/ runtimeFlowControl, object selfObject) { Assert.NotNull(parent); _parent = parent; _top = parent.Top; _selfObject = selfObject; _runtimeFlowControl = runtimeFlowControl; _methodAttributes = RubyMethodAttributes.PrivateInstance; }
public static BlockParam/*!*/ CreateBfcForLibraryMethod(Proc/*!*/ proc) { Assert.NotNull(proc); bool isProcConverter; if (proc.Kind == ProcKind.Block) { var rfc = new RuntimeFlowControl(); rfc._activeFlowControlScope = rfc; proc.Converter = rfc; proc.Kind = ProcKind.Proc; isProcConverter = true; } else { isProcConverter = false; } return new BlockParam(proc, BlockCallerKind.Yield, isProcConverter, null, null); }
public static void MethodRedo(RuntimeFlowControl /*!*/ rfc) { throw new LocalJumpError("unexpected redo", rfc); }
public static RuntimeFlowControl CreateRfcForMethod(Proc proc) { var result = new RuntimeFlowControl(); result._activeFlowControlScope = result; result.InitializeRfc(proc); return result; }
public static RubyModuleScope/*!*/ CreateModuleScope(LocalsDictionary/*!*/ locals, RubyScope/*!*/ parent, RuntimeFlowControl/*!*/ rfc, RubyModule/*!*/ module) { Assert.NotNull(locals, parent, rfc, module); // TODO: RubyModuleScope scope = new RubyModuleScope(parent, locals, null, false); scope.Initialize(rfc, RubyMethodAttributes.PublicInstance, module); scope.SetModule(module); scope.SetDebugName((module.IsClass ? "class" : "module") + " " + module.Name); return scope; }
public static bool MethodYieldRfc(RuntimeFlowControl rfc, BlockParam/*!*/ yieldedBlockFlowControl, object returnValue) { Assert.NotNull(yieldedBlockFlowControl); switch (yieldedBlockFlowControl.ReturnReason) { case BlockReturnReason.Retry: case BlockReturnReason.Return: // The result that the caller returns already is RetrySingleton/MethodUnwinder, // the call-site is with a block (to which we are yielding) and will handle retry/return. return true; case BlockReturnReason.Break: YieldMethodBreak(rfc, yieldedBlockFlowControl, returnValue); return true; } return false; }
public static RubyTopLevelScope/*!*/ CreateWrappedTopLevelScope(LocalsDictionary/*!*/ locals, Scope/*!*/ globalScope, LanguageContext/*!*/ language, out object self, out RuntimeFlowControl/*!*/ rfc) { RubyContext context = (RubyContext)language; RubyModule module = context.CreateModule(null, null, null, null, null, null, null); object mainObject = new Object(); RubyClass mainSingleton = context.CreateMainSingleton(mainObject, new[] { module }); RubyGlobalScope rubyGlobalScope = context.InitializeGlobalScope(globalScope, false); RubyTopLevelScope scope = new RubyTopLevelScope(rubyGlobalScope, null, locals); scope.Initialize(new RuntimeFlowControl(), RubyMethodAttributes.PrivateInstance, rubyGlobalScope.MainObject); scope.SetDebugName("top-level-wrapped"); scope.SelfObject = mainObject; scope.SetModule(module); self = scope.SelfObject; rfc = scope.RuntimeFlowControl; return scope; }
// post-yield break ops: private static void YieldMethodBreak(RuntimeFlowControl rfc, BlockParam/*!*/ yieldedBlockFlowControl, object returnValue) { Assert.NotNull(yieldedBlockFlowControl); // target proc-converter: RuntimeFlowControl targetFrame = yieldedBlockFlowControl.TargetFrame; Debug.Assert(targetFrame != null); if (targetFrame.IsActiveMethod) { // optimize break to the current frame: if (targetFrame == rfc) { return; } else { throw new MethodUnwinder(targetFrame, returnValue); } } else { throw new LocalJumpError("break from proc-closure"); } }
internal BlockReturnResult(RuntimeFlowControl /*!*/ targetFrame, object returnValue) { Assert.NotNull(targetFrame); TargetFrame = targetFrame; ReturnValue = returnValue; }
internal void LeaveMethod() { Debug.Assert(!(this is RubyBlockScope) && !(this is RubyModuleScope)); _activeFlowControlScope = null; }
internal BlockReturnResult(RuntimeFlowControl/*!*/ targetFrame, object returnValue) { Assert.NotNull(targetFrame); TargetFrame = targetFrame; ReturnValue = returnValue; }
public static Proc/*!*/ DefineBlock(RubyScope/*!*/ scope, RuntimeFlowControl/*!*/ runtimeFlowControl, object self, Delegate/*!*/ clrMethod, int parameterCount, BlockSignatureAttributes attributesAndArity, string sourcePath, int startLine) { Assert.NotNull(scope, clrMethod); // closes block over self and context BlockDispatcher dispatcher = BlockDispatcher.Create(clrMethod, parameterCount, attributesAndArity); Proc result = new Proc(ProcKind.Block, self, scope, sourcePath, startLine, dispatcher); result.Owner = runtimeFlowControl; return result; }
internal MethodUnwinder(RuntimeFlowControl/*!*/ targetFrame, object returnValue) : base(returnValue) { Assert.NotNull(targetFrame); TargetFrame = targetFrame; }