in packages/sqrl/src/compile/SqrlParserState.ts [233:296]
pushStatement(ast: Ast) {
invariant(
this._pushStatement !== null,
"ParserState push statement not set"
);
if (ast.type === "let") {
if (ast.expr.type === "call" && ast.expr.func === INPUT_FUNCTION) {
if (!this.slotIsEmpty(ast.feature)) {
throw buildSqrlError(ast, "Multiple definitions of feature");
}
if (this.remainingInputs.hasOwnProperty(ast.feature)) {
this.slots[ast.feature] = new SqrlConstantSlot(
ast.feature,
this.remainingInputs[ast.feature]
);
delete this.remainingInputs[ast.feature];
} else {
this.slots[ast.feature] = new SqrlInputSlot(ast.feature);
}
return;
}
} else if (
ast.type === "call" &&
ast.func === "_resetReplaceableFeatures"
) {
sqrlInvariant(
ast,
ast.args.length === 0,
"Expected no arguments to _resetReplaceableFeatures"
);
this.resetReplaceableFeatures();
return;
}
ast = this.transform(ast);
if (ast.type === "let") {
const oldSlot = this.slots[ast.feature];
if (
this.slotIsEmpty(ast.feature) ||
(oldSlot instanceof SqrlInputSlot && this.allowReplaceInput) ||
(oldSlot instanceof SqrlFixedSlot && oldSlot.replaceable)
) {
this.slots[ast.feature] = new SqrlFeatureSlot(ast.feature);
}
const slot = this.slots[ast.feature];
if (!(slot instanceof SqrlFeatureSlot)) {
throw buildSqrlError(ast, "Feature was previously defined");
}
slot.mergeGlobal(ast, this.globalWhere, (ast: Ast, globalWhere: Ast) =>
this.combineWithProvidedGlobalWhere(ast, globalWhere)
);
} else if (ast.type === "rule") {
if (!this.slotIsEmpty(ast.name)) {
throw buildSqrlError(ast, "Feature was previously defined");
}
const slot = new SqrlRuleSlot(ast.name);
this.slots[ast.name] = slot;
slot.setRule(ast as RuleAst, this.globalWhere);
} else {
this._pushStatement(ast);
}
}