VAPPad is a VAP file editor, bringing the modern IDE features to the VAP editing.

VAPPad 1.0 is ready and can be downloaded as part of VHelper 3.1 suite to increase your productivity.


No installation is required, just download the zip file, unzip and double click vappad.exe to run.

Click here to go to download page

For trial purpose, you need request an activation code for the full features.


In addition to the syntax highlighting

Live Errors

VAPPad shows you syntax and semantic errors immediately. No need to wait starting the VISSIM simulation. This should save you the back and forth time between VISSIM and a regular editor and is particularly useful when you have a large VISSIM network which takes long time to start.

Errors are shown as squiggles and in the error list.

Live errors demo 1

Another example - Subroutine not defined

Live errors demo 2

To see full list of errors VAP can squiggle, scroll down to the section before the VAP language introduction.

Statement Completion

You can manually trigger VAP keywords and 68 internal functions with the usual shortcuts: Ctrl+Space.

Statement completion demo

Auto Format

Automatically indent and beautify your code to improve readability.

Auto Format demo

Function Quick Info

Hover over internal functions to see a Quick Info tooltip.

Quick info demo

Function Parameter Info

Move the caret in the function arguments to match the corresponding parameters.

Parameter info demo

Macro Drop-down List & Folding

Shows available macros and navigate to the corresponding one after selection. Collapse and expand the macros.

Macro drop-down and Folding demo

Delimiter Matching

Press "Ctrl+]" when next to a parenthesis () or bracket [] to navigate to its matching delimiter, or "Shift+Ctrl+]" to select to its matching delimiter.

Delimiter demo

Word Highlighting

Highlight the same token

Highlight demo

Mor Errors that VAPPad can Squiggle

VAP Programming Language Introduction


VAP (vehicle actuated programming) is an optional add-on module of VISSIM for the simulation of programmable, phase or stage based, traffic actuated signal controls.

The latest version of VAP interpreter DLL is 2.16-16 (2016-08-15) at this time of writing.

VAP language itself is a dynamic, case insensitive, single scope (global scope), procedural programming language. It is similar to Python or Lua.

A First Program


VAP_Frequency 1;



MaxGreen2 = 50,
MaxGreen4 = 80;



field[3,4] = [[0, 3, 4.6, 1.23], [1.3, 4, 0, 0.1], [1, 2, 3, 4]],
tClearance[4] = [0,3,0,3];

    IF Not init THEN
        Set_sg( 1 , off );
        LowOccFlag := 1;
        init := 1;
    x := 1

    y := 2


GOSUB test1;
GOSUB test2

It consists of 6 sections: Program, VAP_Frequency, Const, Array, Subroutine(s) and main sections.

VAP_Frequency, Const, Array and Subroutine(s) are optional, but the order matters. For example, if you put VAP_Frequency after the Const segment, you will get an error.

Program Header, Controller Frequency, Constants and Array must end with a semicolon. Subroutine(s) and main sections must end with a dot .

If you define a segment, the contents of that segment can not be empty. the following empty subroutine will have parse error

/* empty subroutine will cause parse error */

Program Header

The first command of a VAP program (in a *.vap file) must consist of the keyword PROGRAM, the name of the program (as a valid identifier) and a semicolon ; .

Controller Frequency

This declaration consists of the keyword VAP_Frequency, an integer value between 1 and 10 (the number of passes through the VAP logic per simulation second - default value is 1 if skipped) and a semicolon ;.

The controller frequency needs to be a factor of the simulation resolution (time steps per simulation second).


User defined constants can be defined in this section.

A definition consists of identifier, an equal sign = and constant value. If you have multiple constants, separate them by comma ,, then end with a semicolon ;.

An equal sign must be used, := is considered as an assignment statement.

If you try to re-assign a value to a constant, VISSIM will report an error

MaxGreen2 = 50,
MaxGreen6 = MaxGreen2,   /* OK, bound to a previous defined constant */

MaxGreen4 := 50;         /* Error, must use =, not :=*/
MaxGreen8 := MaxGreen3;  /* Error, MaxGreen3 is not defined before/

/* In the Subroutine or Main Segment */
MaxGreen2 := 100;        /* Error, re-assign a constant */


Array (up to two dimensional) can be defined in the Array section.

Unlike typical C family language, array values are initialized by the same bracket [] as in the rank definition, instead of braces {}


tClearance[4] = [0,3,0,3];


A subroutine can not be empty, and it must end with a dot ., and there is no explicit return command.

Any number of subroutines may be defined (only limited by RAM space). Any predefined subroutine can be called inside a program using the GOSUB command.

You can call another subroutine within a subroutine. Multiple Subroutine order does not matter in the sub sections, unlike functions in C language.

Unlike VAP 2.16 manual says on page 10

However, there is no form of recursion allowed. Therefore the currently active subroutine cannot call itself.

I find that a recursion is allowed and you can use GOSUB to call the subroutine itself, as long as you provide an termination criteria not go into endless loop.

Main Segment

Like subroutines, it consists of multiple statements delimited by semicolon ;. The main program can not be empty and must end with a dot ..

Everything after . of main segment is ignored, so make sure all your subroutines are defined before the main program segment.

Language Elements


An identifer is a name used to identify a variable, a constant, a subroutine or a label. An identifer must start with a letter followed by zero or more letters, underscores and digits (0 to 9).

a := 1;            /* OK */
a10 := 10;         /* OK */
a_number := 10;    /* OK */

2b := 5;      /* Error, starts with digit */
_cd := 6;     /* Error, starts with underscore _ */
b# := 10;     /* Error, invalid char # */
$m := 10;     /* Error, starts with $ */

VAP is not case sensitive, abc and ABC points to the same variable. IF and if are considered as the same keywords.



keywords can not be used as variable, constant, subroutine and label name

VAP has 68 internal functions, those names are reserved too. For example

Cycle_second T Umlaufsekunde T
Cycle_time Tc Umlaufzeit Tu
Detection Det Anmeldung Anm
Front_ends F_e Vorderkanten Vka
Intergreen Intg Zwischenzeit Zz

Please note every function has an English long name, English short name, German long name and a German short name.

zz := 10; /* Error, zz is a short German name for Intergreen function */

VAP also has 11 signal display constants reserved as keywords.

Display Meaning
amber_f (amber flashing)
green_f (green flashing)
redgreen_f (red-green alternating)
red_f (red flashing)
redamber (red and amber together)
off_red (off meaning ‘red’)
off (off meaning ‘green’)


VAP has two types of variables, regular and timer variables. All variables reset to zero when the simulation starts.

You use START, START_AT, STOP and RESET to change timer variables. Once a timer variable is started, its value is increased by the length of the controller time step (reciprocal of the controller frequency) at the start of each pass through the logic.

Start (phase2Clearance);
Stop (phase2Clearance);
Reset (phase2Clearance);

Timer variable cannot be changed later by an assignment statement, and vice versa. For example, if you try to assign phase2Clearance to 4, VISSIM will report an error.

phase2Clearance := 4; /* Error, can not assign a timer variable */

a := 10;
Start(a);            /* Error, can not start/stop/reset a normal variable */

VAP has dynamic type system, a variable can be assigned to integer, then bound to a double later.

x := 10;
x := 3.14; /* do this is fine, rebound to a double floating point number*/

If a varialbe is initialized, but never used later, there will be a warning for this.

There is no local scope in VAP, all variables and constants are at global scope, a variable defined in one Subroutine can be accessed or reassigned in another subroutine or main segment.


VAP has the following operators, start with the highest precedence to lowest

Precedence Operator Meaning
6 - Highest () Parentheses
5 NOT logical NOT (unary)
4 AND logical AND (binary)
4 * , / Multiplication, Division
4 % , \ Modulo, integer division
3 OR logical OR (binary)
3 + , - Addition, Subtraction (binary)
2 =, <>, <, <=, >, >= comparison
1 - negate (unary)

All operators are left-associative. The precedence order is different from well established norms in C family, I personally feel this is against my expectation and should stick to the C common convention.

a := 2 + -1;    /* Error */
a := 2 - -1;    /* Error */

a := 2 - (-1)   /* OK, Wrap in () */
a := -3 - 2;      /* What's the value? it is -5 as expected, seems evaluated as (-3)-2, this is against the precedence order, should be => -(3-2) => -1  */

b := 4 Or -1;   /* Error */
b := 4 And -2;  /* Error */
if 1 + 1 = 2 And 2 - 2 = 0 then /* parse error */

if (1 + 1 = 2) And (2 - 2 = 0) then /* use (), OK */

if 3 > 2 and 2 > 1 then  /* parse error, however technically it parse => 3>1>1 => 1>1 => False(0)*/

v := 5-2 Or 2-1; /* the value is 0, because OR has same precedence as +/-, => 3 Or 2 -1 => 1 - 1 => 0  */
w := (5-2) Or (2-1); /* as expected 3 Or 1 => 1 */

y := -2 and 4;  /* the value is -1 as expected */
x := -2 or 4;   /* the value is 1, NOT expected, seems VAP evaluated as (-2) or 4, however following precedence table strictly, unary - should have the lowest precedence, then should be evaluated as - (2 or 4)  */

c := 5-2 and 2-1; /* the value is 3 as expected, and has the higher precedence => 5-1-1=>3 */
d := (5-2) and (2-1); /* the value is 1 as expected => 3 and 1 =>1 */
e := 2 or 2 + 1; /* the value is 2 as expected => 1 + 1 => 2 */
f := 2 or (2 + 1); /* the value is 1 as expected => 2 or 3 => 1 */

if -10 * 2 + 10 = -10 then /* Technically it should not parse and VAPPad flag this, however VAP evaluate this expression to true, seems treated (-10) * 2 + 10 = (-10)*/
    y := 1
    y := 0;

it is strongly recommended to use parenthesis to denote what exactly you want


/* /* ok comments */
/* /* invalid nested comment blocks */ */



Integer and double floating point numbers. Integer must be within [-2147483639, 2147483639], which is different from typical 32 bit integer range in C# or Java [-2147483648, 2147483647].

Floating number must start with a digit and no scientific notation is allowed either.

x := 10;          /* OK */
y := 3.14159;     /* OK */

a := .5           /* Error */
b := 1.54334E16   /* Error */
c := 2147483647   /* Error, out of range */

big := 2147483650.2 + 10.2; /* value is 2147483660 using trace, seems rounded */
No string types

0 is false, any non zero is true. All variables reset to zero when the simulation starts

if -1 then
    x := 10;
    x := 5;

if 0 then
    y := 10;
    y := 5;

The value of variable x is 10, y is 5

a := 1 and 2;
b := not a;

The value of variable a is 1, b is 0

Please note there are no boolean literals, True or False, they are interpreted as undefined variables

if 10 > 1 = True then
    x := 1;   /* this never will get executed */

if TRUE then
    a := 1;
    a := 0;

What's value for variable a? Yes, it's 0


Assignment Statement

Simple assignment to a variable is how you create a new variable or rebind an existing one to a new value.

x := 1

Please note use := not equal symbol =

Array value can also be on the left side of assignment statement

arr[3] := 10
Gosub Statement

The GOSUB command calls the specified SUBROUTINE. After executing the subroutine, program execution continues with the next command following the GOSUB command.

If Statement

IF-THEN-END or IF-THEN-ELSE-END, the expression following the key word IF is evaluated first. If the result is other than 0, the statements following THEN will be executed. Otherwise, the program execution will be continued either with the statements following the optional ELSE-clause or with the statements following END if there is no ELSE-clause.

IF 1 > 0 THEN
    a := 5
    a := 10

The semicolon at the last statement of THEN block and ELSE block is optional.

Goto Statement

There is no While or For loops in VAP, use Goto. Program execution continues at the command referenced by the jump label identifier following the jump command.

The jump label identifier must be directly followed (maximum of one blank space) by a colon


The WAIT_AT-UNTIL command can be used to assemble a time loop. Firstly the expression following UNTIL is be evaluated. If its value is zero(false), program execution is interrupted for the current controller time step and will continue in the next controller time step, repeating the evaluation of the expression following the WAIT_AT command. Otherwise, program execution continues with the next command after the label following WAIT_AT.

WAIT_AT Stage1 UNTIL t_actual = T1;

Following functions can be used as statement in VAP


All the rest of functions like Presence can only be used as expressions.

x := Presence (2) /* any vehicle front ends detected on detector #2 */

Functions below have to be used like a constant, no parentheses () are used

t_actual := Cycle_second - offset;
Trace Statement

Like Console.log() in javascript, you can use Trace to print out the variables and more. Please see the manual for detailed description.

Trace(Variable(x, y));


Use NOTRACE to deactivates the trace mode and writes a line of “+” signs in the trace file in order to document the end of the latest trace protocol.

Possible Manual Problems