Skip to content
Snippets Groups Projects
Commit ccb4e0ff authored by xo30xoqa's avatar xo30xoqa
Browse files

Wrote @respond, @trait and @here macros for the species DSL

Also wrote the documentation for @species and @here. Actually getting
the code to run will be the next challenge ;-)
parent 4ad42b92
No related branches found
No related tags found
No related merge requests found
...@@ -24,6 +24,37 @@ end ...@@ -24,6 +24,37 @@ end
### MACROS IMPLEMENTING THE DOMAIN-SPECIFIC LANGUAGE FOR DEFINING SPECIES ### MACROS IMPLEMENTING THE DOMAIN-SPECIFIC LANGUAGE FOR DEFINING SPECIES
"""
@species(name, body)
A macro used to create new species definitions for the nature model.
This is effectively a simple domain-specific language, establishing a
custom syntax to describe species' biology:
```julia
@species name begin
initialise! = initrandompopulation()
phase = "phase1"
...
@phase phase1 begin
...
end
end
```
The definition body (enclosed in the begin/end block) has two sections.
First comes a list of species-specific parameters, which are assigned
just like normal variables. Second come one or more phase definitions,
that describe the behaviour of the species during various parts of its
life cycle (see the documentation to `@phase` for details).
There are two parameters that all species must define:
- `initialise!` should specify a function that will be used to create
the starting population for this species. This function must take
exactly one argument (an `AgentBasedModel` object).
- `phase` should be a string specifying the name of the first phase
that individuals of this species will be assigned to on birth.
"""
macro species(name, body) macro species(name, body)
funcname = "speciesfunction_"*name funcname = "speciesfunction_"*name
quote quote
...@@ -40,10 +71,70 @@ macro species(name, body) ...@@ -40,10 +71,70 @@ macro species(name, body)
end end
end end
"""
@phase(name, body)
This macro is designed to be used within a species definition block (i.e. within
the body of a call to `@species`).
The idea behind this is that species show very different behaviour during different
phases of their lives. Therefore, `@phase` can be used define the behaviour for one
such phase, and the conditions under which the animal transitions to another phase.
`@phase` works by creating a function that will be called by the model if the
animal is in the relevant phase. When it is called, it has access to the following
variables:
- `animal` a reference to the animal itself. This provides access to `animal.age`,
`animal.sex`, and `animal.traits` (a dict that gives access to all species parameters).
- `model` a reference to the model world (an object of type `AgentBasedModel`).
This allows access to `model.date` (the current simulation date) and
`model.landscape` (a two-dimensional array of pixels containing geographic
information).
The utility macros `@respond`, `@trait`, and `@here` can be used within the body of
`@phase` as short-hand for common expressions.
To transition an individual to another phase, simply redefine its phase variable:
`@trait(phase) = "newphase"`.
"""
macro phase(name, body) macro phase(name, body)
:($(esc(name)) = function(animal::Animal, model::AgentBasedModel) $body end) :($(esc(name)) = function(animal::Animal, model::AgentBasedModel) $body end)
end end
"""
@respond(eventname, body)
Define how an animal responds to a landscape event that affects its current position.
This can only be used nested within `@phase`.
"""
macro respond(eventname, body)
quote
if $(esc(eventname)) in @here(events)
$body
end
end
end
"""
@trait(traitname)
A utility macro to quickly access an animal's trait value.
This can only be used nested within `@phase`.
"""
macro trait(traitname)
:(animal.traits[string($(QuoteNode(name)))])
end
"""
@here(property)
A utility macro to quickly access a property of the animal's current position.
This can only be used nested within `@phase`.
"""
macro here(property)
:(model.landscape[animal.pos...].$(property))
end
### FUNCTIONS INTEGRATING THE NATURE MODEL WITH THE REST OF PERSEPHONE ### FUNCTIONS INTEGRATING THE NATURE MODEL WITH THE REST OF PERSEPHONE
......
...@@ -8,15 +8,21 @@ ...@@ -8,15 +8,21 @@
@species Skylark begin @species Skylark begin
lifeexpectancy = 365*5 initialise! = initrandompopulation()
phase = "egg" phase = "egg"
lifeexpectancy = 365*5
eggharvestmortality = 0.9
@phase egg begin @phase egg begin
if !parentsalive(animal) if !parentsalive(animal)
killanimal(animal) killanimal(animal)
end end
@respond harvest killanimal(animal, eggharvestmortality)
if animal.age == 14 if animal.age == 14
changephase("nestling") @trait(phase) = "nestling"
end end
end end
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment