public TemplateFrameAttributeViewModel(EvalTemplateEvent @event, HashSet<string> hiddenAttributes) { if (@event == null) throw new ArgumentNullException("event"); this._event = @event; Template template = _event.Frame.Template; IDictionary<string, object> attributes = template.GetAttributes(); if (attributes != null) { List<AttributeViewModel> attributesList = new List<AttributeViewModel>(); foreach (var attribute in attributes) { bool hidden = !hiddenAttributes.Add(attribute.Key); attributesList.Add(new AttributeViewModel(attribute.Key, attribute.Value, hidden, GetAttributeEvents(template, attribute.Key))); } _attributes = attributesList.AsReadOnly(); } }
protected virtual int ExecuteImpl(ITemplateWriter @out, TemplateFrame frame) { Template self = frame.Template; int start = @out.Index; // track char we're about to Write Bytecode prevOpcode = Bytecode.Invalid; int n = 0; // how many char we Write out int nargs; int nameIndex; int addr; string name; object o, left, right; Template st; object[] options; byte[] code = self.impl.instrs; // which code block are we executing int ip = 0; while (ip < self.impl.codeSize) { if (trace || _debug) Trace(frame, ip); Bytecode opcode = (Bytecode)code[ip]; frame.InstructionPointer = ip; ip++; //jump to next instruction or first byte of operand switch (opcode) { case Bytecode.INSTR_LOAD_STR: int strIndex = GetShort(code, ip); ip += Instruction.OperandSizeInBytes; operands[++sp] = self.impl.strings[strIndex]; break; case Bytecode.INSTR_LOAD_ATTR: nameIndex = GetShort(code, ip); ip += Instruction.OperandSizeInBytes; name = self.impl.strings[nameIndex]; try { o = GetAttribute(frame, name); if (o == Template.EmptyAttribute) o = null; } catch (AttributeNotFoundException) { _errorManager.RuntimeError(frame, ErrorType.NO_SUCH_ATTRIBUTE, name); o = null; } operands[++sp] = o; break; case Bytecode.INSTR_LOAD_LOCAL: int valueIndex = GetShort(code, ip); ip += Instruction.OperandSizeInBytes; o = self.locals[valueIndex]; if (o == Template.EmptyAttribute) o = null; operands[++sp] = o; break; case Bytecode.INSTR_LOAD_PROP: nameIndex = GetShort(code, ip); ip += Instruction.OperandSizeInBytes; o = operands[sp--]; name = self.impl.strings[nameIndex]; operands[++sp] = GetObjectProperty(frame, o, name); break; case Bytecode.INSTR_LOAD_PROP_IND: object propName = operands[sp--]; o = operands[sp]; operands[sp] = GetObjectProperty(frame, o, propName); break; case Bytecode.INSTR_NEW: nameIndex = GetShort(code, ip); ip += Instruction.OperandSizeInBytes; name = self.impl.strings[nameIndex]; nargs = GetShort(code, ip); ip += Instruction.OperandSizeInBytes; // look up in original hierarchy not enclosing template (variable group) // see TestSubtemplates.testEvalSTFromAnotherGroup() st = self.Group.GetEmbeddedInstanceOf(frame, name); // get n args and store into st's attr list StoreArguments(frame, nargs, st); sp -= nargs; operands[++sp] = st; break; case Bytecode.INSTR_NEW_IND: nargs = GetShort(code, ip); ip += Instruction.OperandSizeInBytes; name = (string)operands[sp - nargs]; st = self.Group.GetEmbeddedInstanceOf(frame, name); StoreArguments(frame, nargs, st); sp -= nargs; sp--; // pop template name operands[++sp] = st; break; case Bytecode.INSTR_NEW_BOX_ARGS: nameIndex = GetShort(code, ip); ip += Instruction.OperandSizeInBytes; name = self.impl.strings[nameIndex]; IDictionary<string, object> attrs = (IDictionary<string, object>)operands[sp--]; // look up in original hierarchy not enclosing template (variable group) // see TestSubtemplates.testEvalSTFromAnotherGroup() st = self.Group.GetEmbeddedInstanceOf(frame, name); // get n args and store into st's attr list StoreArguments(frame, attrs, st); operands[++sp] = st; break; case Bytecode.INSTR_SUPER_NEW: nameIndex = GetShort(code, ip); ip += Instruction.OperandSizeInBytes; name = self.impl.strings[nameIndex]; nargs = GetShort(code, ip); ip += Instruction.OperandSizeInBytes; SuperNew(frame, name, nargs); break; case Bytecode.INSTR_SUPER_NEW_BOX_ARGS: nameIndex = GetShort(code, ip); ip += Instruction.OperandSizeInBytes; name = self.impl.strings[nameIndex]; attrs = (IDictionary<string, object>)operands[sp--]; SuperNew(frame, name, attrs); break; case Bytecode.INSTR_STORE_OPTION: int optionIndex = GetShort(code, ip); ip += Instruction.OperandSizeInBytes; o = operands[sp--]; // value to store options = (object[])operands[sp]; // get options options[optionIndex] = o; // store value into options on stack break; case Bytecode.INSTR_STORE_ARG: nameIndex = GetShort(code, ip); name = self.impl.strings[nameIndex]; ip += Instruction.OperandSizeInBytes; o = operands[sp--]; attrs = (IDictionary<string, object>)operands[sp]; attrs[name] = o; // leave attrs on stack break; case Bytecode.INSTR_WRITE: o = operands[sp--]; int n1 = WriteObjectNoOptions(@out, frame, o); n += n1; nwline += n1; break; case Bytecode.INSTR_WRITE_OPT: options = (object[])operands[sp--]; // get options o = operands[sp--]; // get option to Write int n2 = WriteObjectWithOptions(@out, frame, o, options); n += n2; nwline += n2; break; case Bytecode.INSTR_MAP: st = (Template)operands[sp--]; // get prototype off stack o = operands[sp--]; // get object to map prototype across Map(frame, o, st); break; case Bytecode.INSTR_ROT_MAP: int nmaps = GetShort(code, ip); ip += Instruction.OperandSizeInBytes; List<Template> templates = new List<Template>(); for (int i = nmaps - 1; i >= 0; i--) templates.Add((Template)operands[sp - i]); sp -= nmaps; o = operands[sp--]; if (o != null) RotateMap(frame, o, templates); break; case Bytecode.INSTR_ZIP_MAP: st = (Template)operands[sp--]; nmaps = GetShort(code, ip); ip += Instruction.OperandSizeInBytes; List<object> exprs = new List<object>(); for (int i = nmaps - 1; i >= 0; i--) exprs.Add(operands[sp - i]); sp -= nmaps; operands[++sp] = ZipMap(frame, exprs, st); break; case Bytecode.INSTR_BR: ip = GetShort(code, ip); break; case Bytecode.INSTR_BRF: addr = GetShort(code, ip); ip += Instruction.OperandSizeInBytes; o = operands[sp--]; // <if(expr)>...<endif> if (!TestAttributeTrue(o)) ip = addr; // jump break; case Bytecode.INSTR_OPTIONS: operands[++sp] = new object[Compiler.TemplateCompiler.NUM_OPTIONS]; break; case Bytecode.INSTR_ARGS: operands[++sp] = new Dictionary<string, object>(); break; case Bytecode.INSTR_PASSTHRU: nameIndex = GetShort(code, ip); ip += Instruction.OperandSizeInBytes; name = self.impl.strings[nameIndex]; attrs = (IDictionary<string, object>)operands[sp]; PassThrough(frame, name, attrs); break; case Bytecode.INSTR_LIST: operands[++sp] = new List<object>(); break; case Bytecode.INSTR_ADD: o = operands[sp--]; // pop value List<object> list = (List<object>)operands[sp]; // don't pop list AddToList(list, frame, o); break; case Bytecode.INSTR_TOSTR: // replace with string value; early eval operands[sp] = ToString(frame, operands[sp]); break; case Bytecode.INSTR_FIRST: operands[sp] = First(frame, operands[sp]); break; case Bytecode.INSTR_LAST: operands[sp] = Last(frame, operands[sp]); break; case Bytecode.INSTR_REST: operands[sp] = Rest(frame, operands[sp]); break; case Bytecode.INSTR_TRUNC: operands[sp] = Trunc(frame, operands[sp]); break; case Bytecode.INSTR_STRIP: operands[sp] = Strip(frame, operands[sp]); break; case Bytecode.INSTR_TRIM: o = operands[sp--]; if (o.GetType() == typeof(string)) { operands[++sp] = ((string)o).Trim(); } else { _errorManager.RuntimeError(frame, ErrorType.EXPECTING_STRING, "trim", o.GetType()); operands[++sp] = o; } break; case Bytecode.INSTR_LENGTH: operands[sp] = Length(operands[sp]); break; case Bytecode.INSTR_STRLEN: o = operands[sp--]; if (o.GetType() == typeof(string)) { operands[++sp] = ((string)o).Length; } else { _errorManager.RuntimeError(frame, ErrorType.EXPECTING_STRING, "strlen", o.GetType()); operands[++sp] = 0; } break; case Bytecode.INSTR_REVERSE: operands[sp] = Reverse(frame, operands[sp]); break; case Bytecode.INSTR_NOT: operands[sp] = !TestAttributeTrue(operands[sp]); break; case Bytecode.INSTR_OR: right = operands[sp--]; left = operands[sp--]; operands[++sp] = TestAttributeTrue(left) || TestAttributeTrue(right); break; case Bytecode.INSTR_AND: right = operands[sp--]; left = operands[sp--]; operands[++sp] = TestAttributeTrue(left) && TestAttributeTrue(right); break; case Bytecode.INSTR_INDENT: strIndex = GetShort(code, ip); ip += Instruction.OperandSizeInBytes; Indent(@out, frame, strIndex); break; case Bytecode.INSTR_DEDENT: @out.PopIndentation(); break; case Bytecode.INSTR_NEWLINE: try { if (prevOpcode == Bytecode.INSTR_NEWLINE || prevOpcode == Bytecode.INSTR_INDENT || nwline > 0) { @out.Write(Environment.NewLine); } nwline = 0; } catch (IOException ioe) { _errorManager.IOError(self, ErrorType.WRITE_IO_ERROR, ioe); } break; case Bytecode.INSTR_NOOP: break; case Bytecode.INSTR_POP: sp--; // throw away top of stack break; case Bytecode.INSTR_NULL: operands[++sp] = null; break; case Bytecode.INSTR_TRUE: operands[++sp] = true; break; case Bytecode.INSTR_FALSE: operands[++sp] = false; break; case Bytecode.INSTR_WRITE_STR: strIndex = GetShort(code, ip); ip += Instruction.OperandSizeInBytes; o = self.impl.strings[strIndex]; n1 = WriteObjectNoOptions(@out, frame, o); n += n1; nwline += n1; break; // TODO: generate this optimization //case Bytecode.INSTR_WRITE_LOCAL: // valueIndex = GetShort(code, ip); // ip += Instruction.OperandSizeInBytes; // o = self.locals[valueIndex]; // if (o == Template.EmptyAttribute) // o = null; // n1 = WriteObjectNoOptions(@out, frame, o); // n += n1; // nwline += n1; // break; default: _errorManager.InternalError(self, "invalid bytecode @ " + (ip - 1) + ": " + opcode, null); self.impl.Dump(); break; } prevOpcode = opcode; } if (_debug) { EvalTemplateEvent e = new EvalTemplateEvent(frame, Interval.FromBounds(start, @out.Index)); TrackDebugEvent(frame, e); } return n; }
private int GetIndexOfChild(EvalTemplateEvent parent, EvalTemplateEvent child) { if (parent == null) throw new ArgumentNullException("parent"); if (child == null) throw new ArgumentNullException("child"); TemplateCallHierarchyViewModel hierarchy = new TemplateCallHierarchyViewModel(ViewModel.Visualizer.Interpreter, parent); List<TemplateCallHierarchyViewModel> children = hierarchy.Children; return children.FindIndex(i => i.Event == child); }