A Quick Introduction to Virgil - Methods

This is part of a basic introduction to programming in Virgil and gives an overview of the language, its syntax, and its structures. This page focuses on the basics of declaring, using, and invoking methods.

Overview

program MyProgram {
    entrypoint main = MyComp.main;
}
component MyComp {
    method main(arg: char[][]): int {
        return 0;
    }
    // declare more methods here
}

Methods in Virgil are pieces of code that are associated with a class or component that implement a specific computation. Methods may take parameters and return a value; the names and types of parameters are given in the declaration and can be accessed in the body of a procedure. This tutorial has not yet discussed components, but we can go back to our basic program outline and discuss how to declare and use methods within a single component.

Declaring Methods

method name(arg: type, ...): type {
    // statements
}
method add(a: int, b: int): int {
    return a + b;
}
method run(a: int) {
    . . .
}

Methods can be declared inside of components and classes. A declaration begins with the keyword method, followed by the name of the method (which must be a valid identifier), and then a list of arguments (if any) enclosed in parentheses ( ... ), and then an optional return type. Notice that the syntax for declaring each parameter to the method is similar to the syntax for declaring local variables (see the statements page), with the name of the parameter given first, followed by a colon :, then the type. Unlike local variables, parameters to a method must be given an explicit type. Notice that we can declare methods that do not have a return type by simply omitting the return type in the declaration.

Invoking Methods

method add(a: int, b: int): int {
    return a + b;
}
method run(a: int) {
    local x: int = add(0, 6);
}

Methods can be invoked by simply referring to their name and passing the arguments inside of parentheses ( ... ) following the name of the method to invoke. In the example to the right, the run() method contains a call to the add() method, passing the arguments 0 and 6. At the invocation site, the compiler will check that the number and types of the arguments pass match the declaration of the method. Similarly, the type of the invocation expression will be the declared type of the method.

Returning from a Method

method add(a: int, b: int): int {
    return a + b; // legal
}
method mul(a: int, b: int): int {
    return false; // ERROR
}
method err() {
    return 0; // ERROR
}

Methods that are declared to return a value must have at least one return statement that returns a value of the appropriate declared type. When the program executes a return statement, it will evaluate the expression that is a parameter to the return, producing a value, and then return it to the caller. Similarly, methods that are declared without a return value cannot have return statements that attempt to return a value. All return statements inside of methods without a return value must lack a return value.

Overloading Methods

method add(a: int, b: int): int {
    return a + b;
}
method add(a: int): int { // ERROR
    return a + 3; 
}

Some languages such as C++ and Java allow method overloading, where two or more methods have the same name but different declared argument or return types. Disambiguation between the methods happens at invocation sites of the program by inspecting the types of the parameter and/or the expected type of the return value.

Virgil does not allow method overloading of any kind. Any attempt to declare a method with the same name in the same class or component will result in a compile-time error.

Go back to the tutorial.