Skip to content

Template

WARNING

This type is only available in the language-builder and should not be exposed to the end user.

If you try to use template in a program, vif-sim will return an error.

What is a template

Template is an advanced type which allow you to create "headless" functions.

Templates only have an interface schema and a reference to a memory location.

To tell vif to reference a variable in the inner memory, you need a special type called Resolve which contains the supposed path of a variable in memory.

On compilation, vif-sim will check if interface variables & all Resolve match a valid memory reference.

You only define the types of the interface and the memory, the end user will have to provide a valid memory reference and interface.

null

Create a template

To create a template, first import Template & Resolve from @vifjs/language-builder.

ts
import {
Resolve
,
Template
} from "@vifjs/language-builder/template";

Then create a new class which extends the template.

ts
import {
Resolve
,
Template
} from "@vifjs/language-builder/template";

The super() in the constructor must provides the body of your function.

As said earlier, templates have no idea about the the types of your interface.

To implicitly tell Vif these types should be solved later, use the Resolve function.

Finally you can create a function with a custom name that merges the interface and the body provided.

Example with Timer Pulse

Inner memory

We first declare the inner memory that a Timer must have, as said earlier this is the function static memory.

For a Timer Pulse, the memory will be an udt_impl so we're going to create a new class that extends Udt

ts
// Declare our UDT
export const TPInstance = new Udt({
    IN: new Bool(),
    PT: new Time(),
    Q: new Bool(),
    ET: new Time(),
})

Next we will add it to the provider internal so the users can declare a TPInstance.

ts
export default new Provider(
    {
        // ...
        internal: {
            "TPInstance": TPInstance, 
        }
    }
)
How the end user will see this
ts
import {Provider} from "#source"

const MyFb = new Fb({
    interface: {
        static: {
            Timer: Provider.internal.TPInstance
        }
    }
})

Template

We will create the template by extending the Template class.

The super() needs a function that returns an array of Operations.

This is the same thing as the body() of any POU function block.

ts
class TP extends Template {
    constructor() {
        super(() => {
            return []
        })
    }
}

We need to define the operations, since we're building a Timer we will use a Timer State Machine.

ts
class TP extends Template {
    constructor() {
        super(() => {
            return [
                new Timer_State_Machine({ 
                    // Start when IN is true
                    start: new Compare(new Resolve(["#inner", "IN"]), "=", true), 

                    // TP cannot be cancelled until it's elapsed
                    reset: undefined, 
                    preset_var: new Resolve(["#inner", "PT"]), 
                    timer_var: new Resolve(["#inner", "ET"]), 

                    // Q is always true while the timer is on
                    on_timer_start: [new Assign(new Resolve(["#inner", "Q"]), true)], 
                    on_timer_elapsed: [ 
                        new Assign(new Resolve(["#inner", "Q"]), false), // Set Q to false when the timer is stopped
                        new Internal_Reset(new Resolve(["#inner", "ET"])) // Reset the elapsed time
                    ], 

                    // No need to have reset operations
                    on_timer_reset: [] 
                }) 
            ]
        })
    }
}

Finally we need to provide a function that will build the template an make it available to the end user.

To do this, we need to call the super build function of Template.

build has 2 parameters:

  • innerMemory: The memory that the template will use to store data (in our case TPInstance).
  • callInterface: The interface the end user must fill to call your template.

You are free to name the function the way you like it.

ts
class TP extends Template {
    constructor() {
        super(() => {
            // ...
        })
    }

    public useMyGreatTimer( 
        timer_memory: typeof TPInstance, 
        call_interface: { 
            input: { 
                IN: Bool, 
                PT: Time
            }, 
            output: { 
                Q: Bool, 
                ET: Time
            } 
        }): Operation<void> { 
        return super.build(timer_memory, call_interface) 
    } 
}
How the end user will see this
ts
import {Provider} from "#source"

const MyFb = new Fb({
    interface: {
        static: {
            Timer: Provider.internal.TPInstance.self(),
            triggerTimer: new Bool(true),
            elaspedTime: new Time(),
            outputTimer: new Bool(),
        }
    },
    body() {
        return [
            Provider.internal.TP.useMyGreatTimer({
                input: {
                    IN: this.static.triggerTimer,
                    PT: Time_from({s: 5}),
                },
                output: {
                    ET: this.static.elaspedTime,
                    Q: this.static.outputTimer,
                }
            })
        ]
    }
})