1 // Copyright (c) 1997 James Clark
2 // See the file copying.txt for copying permission.
5 #include "MacroFlowObj.h"
9 #include "Expression.h"
10 #include "Interpreter.h"
11 #include "ProcessContext.h"
14 #ifdef DSSSL_NAMESPACE
15 namespace DSSSL_NAMESPACE {
18 MacroFlowObj::MacroFlowObj(Vector<const Identifier *> &nics,
19 NCVector<Owner<Expression> > &inits,
20 const Identifier *contentsId,
21 Owner<Expression> &body)
22 : def_(new Definition(nics, inits, contentsId, body))
24 size_t n = def_->nics().size();
25 charicVals_ = new ELObj *[n];
26 for (size_t i = 0; i < n; i++)
30 MacroFlowObj::MacroFlowObj(const MacroFlowObj &obj)
31 : CompoundFlowObj(obj), def_(obj.def_)
33 size_t n = def_->nics().size();
34 charicVals_ = new ELObj *[n];
35 for (size_t i = 0; i < n; i++)
36 charicVals_[i] = obj.charicVals_[i];
39 MacroFlowObj::~MacroFlowObj()
41 delete [] charicVals_;
44 FlowObj *MacroFlowObj::copy(Collector &c) const
46 return new (c) MacroFlowObj(*this);
49 CompoundFlowObj *MacroFlowObj::asCompoundFlowObj()
51 if (def_->isCompound())
57 bool MacroFlowObj::hasNonInheritedC(const Identifier *id) const
59 const Vector<const Identifier *> &nics = def_->nics();
60 for (size_t i = 0; i < nics.size(); i++)
66 void MacroFlowObj::setNonInheritedC(const Identifier *id, ELObj *obj, const Location &, Interpreter &)
68 const Vector<const Identifier *> &nics = def_->nics();
69 for (size_t i = 0;; i++) {
77 void MacroFlowObj::traceSubObjects(Collector &c) const
79 size_t n = def_->nics().size();
80 for (size_t i = 0; i < n; i++)
81 c.trace(charicVals_[i]);
82 CompoundFlowObj::traceSubObjects(c);
85 class EmptyStyleObj : public StyleObj {
87 void appendIter(StyleObjIter &) const { }
90 void MacroFlowObj::unpack(VM &vm)
92 size_t n = def_->nics().size();
93 vm.needStack(n + 1 + def_->isCompound());
94 for (size_t i = 0; i < n; i++)
95 *vm.sp++ = charicVals_[i];
96 if (def_->isCompound()) {
97 ELObj *tem = content();
99 tem = new (*vm.interp) ProcessChildrenSosofoObj(vm.interp->initialProcessingMode());
104 void MacroFlowObj::processInner(ProcessContext &context)
106 FOTBuilder &fotb = context.currentFOTBuilder();
107 fotb.startSequence();
108 def_->process(context, this);
112 MacroFlowObj::Definition::Definition(Vector<const Identifier *> &charics,
113 NCVector<Owner<Expression> > &charicInits,
114 const Identifier *contentsId,
115 Owner<Expression> &body)
116 : contentsId_(contentsId)
118 charics.swap(charics_);
119 charicInits.swap(charicInits_);
120 charicInits_.resize(charics_.size());
124 void MacroFlowObj::Definition::process(ProcessContext &context,
127 VM &vm = context.vm();
128 Interpreter &interp = *vm.interp;;
131 StyleStack *saveStyleStack = vm.styleStack;
132 vm.styleStack = &context.currentStyleStack();
133 unsigned saveSpecLevel = vm.specLevel;
134 vm.specLevel = vm.styleStack->level();
136 vm.actualDependencies = &dep;
137 ELObj *obj = context.vm().eval(code_.pointer(), 0, macro);
138 vm.styleStack = saveStyleStack;
139 vm.specLevel = saveSpecLevel;
140 if (!interp.isError(obj)) {
141 ELObjDynamicRoot protect(interp, obj);
142 ((SosofoObj *)obj)->process(context);
146 class UnpackMacroFlowObjInsn : public Insn {
148 UnpackMacroFlowObjInsn(InsnPtr next) : next_(next) { }
149 const Insn *execute(VM &vm) const {
150 ((MacroFlowObj *)*--vm.sp)->unpack(vm);
151 return next_.pointer();
157 void MacroFlowObj::Definition::compile(Interpreter &interp)
160 result = new CheckSosofoInsn(body_->location(), result);
161 int nPush = charics_.size() + (contentsId_ != 0);
162 result = PopBindingsInsn::make(nPush, result);
163 BoundVarList frameVars;
164 for (size_t i = 0; i < charics_.size(); i++) {
165 if (i > 0 && charicInits_[i])
166 charicInits_[i]->markBoundVars(frameVars, 0);
167 frameVars.append(charics_[i], 0);
170 frameVars.append(contentsId_, 0);
171 body_->markBoundVars(frameVars, 0);
172 result = Expression::optimizeCompile(body_, interp,
173 Environment(frameVars, BoundVarList()),
175 for (size_t i = charics_.size(); i > 0; i--) {
176 int stackOffset = int(i) - nPush - 1;
177 if (frameVars[i - 1].boxed())
178 result = new BoxStackInsn(stackOffset, result);
179 InsnPtr ifNull = new SetKeyArgInsn(stackOffset, result);
180 if (charicInits_[i - 1]) {
181 BoundVarList f(frameVars);
183 ifNull = Expression::optimizeCompile(charicInits_[i - 1], interp,
184 Environment(f, BoundVarList()),
188 ifNull = new ConstantInsn(interp.makeFalse(), ifNull);
189 result = new TestNullInsn(stackOffset, ifNull, result);
191 code_ = new UnpackMacroFlowObjInsn(result);
194 #ifdef DSSSL_NAMESPACE