/**
 * Copyright 2018 Twitter, Inc.
 * Licensed under the Apache License, Version 2.0
 * http://www.apache.org/licenses/LICENSE-2.0
 */ import { Ast , CallAst , jsonAst , ConstantAst } from "../ast/Ast" ; import invariant from "../jslib/invariant" ; import SqrlAst from "../ast/SqrlAst" ; import { SerializedSlotBase , SerializedSlot , SerializedStatementSlot , SerializedConstantSlot , SerializedFixedSlot , registerSlotClass , } from "./SerializedSlot" ; export abstract class SqrlSlot { private index : number = null ; name : string ; constructor ( nameOrData ) { if ( typeof nameOrData === "string" ) { this . name = nameOrData ; } else if ( typeof nameOrData . name === "string" ) { this . name = nameOrData . name ; } else { throw new Error ( "Invalid SqrlSlot name" ) ; } } serialize ( ) { return { class : this . constructor . name , name : this . name , } as any ; } deserializor ( data ) { this . index = null ; this . name = data . name ; } abstract finalizedAst ( ) ; getIndex ( ) { invariant ( this . index !== null , "Slot has not yet been assigned an index:: %s" , this . name ) ; return this . index ; } setIndex ( idx ) { invariant ( this . index === null , "Can only set slot index once:: %s" , this . name ) ; this . index = idx ; } } @ registerSlotClass export class SqrlIteratorSlot extends SqrlSlot { finalizedAst ( ) { return SqrlAst . constant ( null ) ; } } @ registerSlotClass export class SqrlStatementSlot extends SqrlSlot { private finalized = false ; private referencedSlots : Set < string > = new Set ( ) ; serialize ( ) { return { ... ( super . serialize ( ) as SerializedStatementSlot ) , referencedSlots : Array . from ( this . referencedSlots ) . sort ( ) , } ; } deserializor ( data ) { super . deserializor ( data ) ; this . finalized = false ; this . referencedSlots = new Set ( data . referencedSlots ) ; } finalizedAst ( ) { this . finalized = true ; return SqrlAst . call ( "_slotWait" , Array . from ( this . referencedSlots ) . map ( ( slotName ) => SqrlAst . slotName ( slotName ) ) ) ; } addWait ( slotName ) { invariant ( ! this . finalized , "Slot cannot be set after it is read: %s" , this . name ) ; this . referencedSlots . add ( slotName ) ; } } @ registerSlotClass export class SqrlConstantSlot extends SqrlSlot { private finalized = false ; ast : ConstantAst ; constructor ( name , value ) { super ( name ) ; this . ast = SqrlAst . constant ( value ) ; } deserializor ( data ) { super . deserializor ( data ) ; this . finalized = false ; this . ast = data . ast ; } serialize ( ) { jsonAst ( this . ast ) ; return { ... ( super . serialize ( ) as SerializedConstantSlot ) , ast : this . ast , } ; } setValue ( value ) { invariant ( this . finalized === false , "constant slot was finalized" ) ; this . ast = SqrlAst . constant ( value ) ; } getValue ( ) { return this . ast . value ; } finalizedAst ( ) { this . finalized = true ; return this . ast ; } } @ registerSlotClass export class SqrlEmptySlot extends SqrlSlot { finalizedAst ( ) { return SqrlAst . constant ( null ) ; } } @ registerSlotClass export class SqrlInputSlot extends SqrlSlot { finalizedAst ( ) { return SqrlAst . constant ( null ) ; } } @ registerSlotClass export class SqrlFixedSlot extends SqrlSlot { constructor ( name , private ast , readonly replaceable = false ) { super ( name ) ; this . ast = ast ; } deserializor ( data ) { super . deserializor ( data ) ; this . ast = data . ast ; data . replaceable = this . replaceable ; } serialize ( ) { jsonAst ( this . ast ) ; return { ... ( super . serialize ( ) as SerializedFixedSlot ) , ast : this . ast , replaceable : this . replaceable , } ; } finalizedAst ( ) { return this . ast ; } }