/// <summary> /// Resolves a single GotoItem by traversing up the tree from the given /// root. Throws an exception if the label cannot be found. /// </summary> /// <param name="root">The node to start the search.</param> /// <param name="item">The item to resolve.</param> static void ResolveGoto(TreeNode/*!*/ root, GotoItem/*!*/ item) { do { foreach (var label in root.Labels) { if (label.Name == item.Name) { item.Target = label; return; } } } // break statements can pass through local definitions while ((item.Name != "<break>" || !root.IsFunction) && (item.Name == "<break>" || root.Passable) && (root = root.Parrent) != null); throw new SyntaxException(string.Format(Resources.LabelNotFound, item.Name), item.Debug); }
/// <summary> /// Called when the item is a goto item. /// </summary> /// <param name="target">The object that was passed to IParseItem.Visit.</param> /// <returns>The passed target or a modification of it.</returns> /// <exception cref="System.ArgumentNullException">If target is null.</exception> public IParseItem Visit(GotoItem target) { if (target == null) throw new ArgumentNullException("target"); tree.DefineGoto(target); return target; }
/// <summary> /// Defines a new GotoItem in the current block. /// </summary> /// <param name="item">The item to define.</param> public void DefineGoto(GotoItem/*!*/ item) { cur.GotoItems.Add(item); }
/// <summary> /// Called when the item is a goto item. /// </summary> /// <param name="target">The object that was passed to IParseItem.Visit.</param> /// <returns>The passed target or a modification of it.</returns> /// <exception cref="System.ArgumentNullException">If target is null.</exception> public IParseItem Visit(GotoItem target) { if (target == null) throw new ArgumentNullException("target"); if (target.Target == null) throw new InvalidOperationException(Resources.ErrorResolveLabel); compiler.CurrentGenerator.Emit(OpCodes.Br, (Label)target.Target.UserData); return target; }