Fork me on GitHub

Skill Reference

This document describes how to define Skills in SARL. Before reading this document, we recommend that you read the General Syntax Reference, and the Capacity Reference.

An Action is code (a public method or function) that transforms a part of the designed system or its environment. This transformation guarantees resulting properties if the system before the transformation satisfies a set of constraints. An Action is defined in terms of pre- and post-conditions.

A Capacity is the specification of a collection of Actions. This specification makes no assumptions about the implementation of each Action. It is used to specify what an Agent can do, what behavior is required for its execution.

A Skill is a collection of Actions implementing a Capacity as described in this specification.

1. Defining a Skill

1.1. Basic Definition

A Skill implements a Capacity and is defined with the skill keyword. This relationship is specified with the implements keyword.

Below, a Skill is defined to output messages on the standard console (defined in the Capacity Reference). Note that all the Actions defined in the Capacity must have a definition (with a body containing code) in the Skill.

skill ConsoleLogging implements Logging {
	def info(text : String) {
		System.out.println(text)
	}
	def debug(text : String) {
		System.err.println(text)
	}
}

1.2. Field Definition

Often it is useful or necessary to base a Skill (a Capacity’s implementation) on attributes (properties or fields).

The following example defines a Skill that uses the standard Java logging library. To avoid creating an instance of the Java logger each time the Capacity’s Actions are invoked, an instance of the Java logger is created and stored in a field of the Skill.

skill StandardJavaLogging implements Logging {
	// A field is defined in the Skill
	val logger = Logger.anonymousLogger
	def info(text : String) {
		logger.info(text)
	}
	def debug(text : String) {
		logger.fine(text)
	}
}

1.3. Action Definition

It is possible to declare methods in the Skill in addition to those specified by the Capacity.

skill MyLogging implements Logging {
	def info(text : String) {
		output(text)
	}
	def debug(text : String) {
		output(text)
	}
	// Define an utility function
	// that is outputting the text
	def output(t : String) {
		System.err.println(t)
	}
}

1.4. Initialization of a skill

Several elements of the skill can be used only after the skill is attached to its owning agent. For example, the value returned by the function getOwner is not null only when the skill is attached to an agent, i.e. its owner.

In order to enable the developer to write a code that is run when the skill is attached, the function install could be defined and implemented. The code below provides an example in which the value returned by getOwner is checked.

def install {
	// Initialization of the skill
	assert getOwner !== null
}

1.5. Uninitialization of a skill

In a similar way as install, it is possible to execute a code when the skill is detached from it owning agent. For this purpose, the uninstall function should be defined, as illustrated below:

def uninstall {
	// Do uninstallation statements
}

1.6. Constructor Definition

It is not necessary to specify a constructor for Skills unless a value will be initialized.

Two constructors are defined in the abstract Skill class:

class Skill extends AgentTrait
		implements IBehaviorGuardEvaluatorReceiver {
	def getReferenceCount : int
}

Example of constructor definition:

// The constructor is mandatory
// for defining the field "logger"
new (l : Logger) {
	super() // Call the super's constructor
	logger = l
}

If no constructor is defined in the skill type and a super-type is declared, implicit constructors will be assumed. Implicit constructors has the same prototypes as the constructors of the super type. Details on implicit constructors are given in the reference documentation related to the synthetic functions.

1.7. Multiple Capacity Implementation

In some situations it is useful to combine more than one capacity in a skill. Below, the MyLogging skill is defined as an implementation of the capacities Logging and LogReader. All the Actions defined in a Capacity must have an implementation in the related Skill.

If two implemented Capacities include the same Action signature, it must be implemented only once in the Skill.

capacity LogReader {
	def open(filename : String) : int
	def info(t : String)
	def close(fid : int)
}
skill MyLogging implements Logging, LogReader {
	// Shared implementation for the methods
	// defind in the two Capacities.
	def info(text : String) {
		System.out.println(text)
	}
	def debug(text : String) {
		System.out.println(text)
	}
	def open(filename : String) : int {
		return 0
	}
	def close(fid : int) {
	}
}

1.8. Extending a Skill

In some situations it is useful to specialize the definition of a Skill. This mechanism is supported by the inheritance feature of SARL, which has the same semantics as the inheritance mechanism of the Java object-oriented language.

The extended Skill is specified just after the extends keyword.

Very Important Note A Skill type can extend only one other Skill type. This is similar to the constraint on the extension of classes in the Java language.

In the following code, the StandardJavaLogging Skill (defined above) is extended to override the info output.

skill ExtendedLogging extends StandardJavaLogging {
	def info(text : String) {
		super.info("INFO: "+text)
	}
}

1.9. Modifiers

Modifiers are used to modify declarations of types and type members. This section introduces the modifiers for the Skill. The modifiers are usually written before the keyword for defining the Skill.

The complete description of the modifiers’ semantic is available in this section.

Skill Modifiers

A Skill may be declared with one or more modifiers, which affect its runtime behavior:

Examples:

public skill Example1 implements CapacityExample {
}
package skill Example2 implements CapacityExample {
}
abstract skill Example3 implements CapacityExample {
}
final skill Example4 implements CapacityExample {
}

Field Modifiers

The modifiers for the fields in a Skill are:

Examples:

public var example1 : Object
protected var example2 : Object
package var example3 : Object
private var example4 : Object
static var example5 : Object

Method Modifiers

The modifiers for the methods in a Skill are:

Examples:

// Public access function
public def example1 { }
// Protected access function
protected def example2 { }
// Package access function
package def example3 { }
// Private access function
private def example4 { }
// Abstract function
abstract def example5
// Not-overridable function
final def example6 { }
// Dispatch functions
dispatch def example7(p : Integer) { }
dispatch def example7(p : Float) { }
// Static / Class function
static def example8 { }

2. Behavior Units of a Skill

The Skill statement permits specifying a subset of the agent’s behavior units inside the skill to make it able to react to the receiving of some event.

on EventName [ Guard ] {
	Statements
}

EventName is the name of event to wait for. Guard is the optional specification of a predicate that may be true for executing the Statements. The statements are executed only if an event with the given name is received, and if the guard is true.

In the guard and the statements, it is possible to use the instance of the received event: the occurrence. This instance is represented by the occurrence keyword. It is an implicit variable as the keywords this and it.

2.1. Generic Events in Handlers

Since the version 0.14 of SARL, it is possible to define an event with generic types. The counterpart of this type of event definition is related to the definition of generic types in the event handlers. The specific of the generic types within the event handlers could be assimilated to an implict guard condition. In other word, the event handler is run only if the received event is matching the specific generic types.

Let the following example in which the event MyGenericEvent is defined with two generic types T1 and T2. Several event handlers have been defined for illustrating multiple cases.

event MyGenericEvent<T1, T2 extends Number> {
	var field0 : T1
	var field1 : T2
}

skill MySkill implements MyCapacity {
	uses Logging
	def oneFunction {}
	on MyGenericEvent {
		info("Run whatever the values of field0 and field1")
	}
	on MyGenericEvent<?, ?> {
		info("Run whatever the values of field0 and field1")
	}
	on MyGenericEvent<String, ?> {
		info("Run if field0 is a String, whatever the value of field1")
	}
	on MyGenericEvent<?, Double> {
		info("Run if field1 is a Double, whatever the value of field0")
	}
	on MyGenericEvent<String, Double> {
		info("Run only if field0 is a String and field1 is a Double")
	}
	on MyGenericEvent<? extends String, Double> {
		info("Run only if field0 is a String and field1 is a Double")
	}
	on MyGenericEvent<Number, Integer> {
		info("Run only if field0 is a String and field1 is a Double")
	}
}

Basically, when an event MyGenericEvent is received, it is associated to the definition of concrete types for T1 and T2. For example, the event corresponding to new MyGenericEvent<String, Double> is received, then T1 is assimilated to String and T2 to Double.

From this example of event occurrence, the activated event handlers will be because the declared geneic types ar ematching <String, Double> from the event:

But, on MyGenericEvent<Number, Integer> is not run because the generic types are not matching those from the event.

3. Built-in Skills

Several Capacities are defined and reserved by the SARL Core Specification. The corresponding Skills are provided by the runtime environment (such as the Janus platform). The built-in Skills are described in the Built-in Capacity Reference.

4. Use of the Skills

Details on the use of Skills may be found in the following:

Copyright © 2014-2024 SARL.io, the Original Authors and Main Authors.

Documentation text and medias are licensed under the Creative Common CC-BY-SA-4.0; you may not use this file except in compliance with CC-BY-SA-4.0. You may obtain a copy of CC-BY-4.0.

Examples of SARL code are licensed under the Apache License, Version 2.0; you may not use this file except in compliance with the Apache License. You may obtain a copy of the Apache License.

You are free to reproduce the content of this page on copyleft websites such as Wikipedia.

Generated with the translator docs.generator 0.14.0.