Skip to content

Commit

Permalink
Optimization: Support any? turtles-on ... compiler optimization
Browse files Browse the repository at this point in the history
- Bump to latest NetLogo with the new optimzation
- Fix bug in `turtles-on` where duplicate agents could be added to an
  agentset
  • Loading branch information
LaCuneta committed Mar 15, 2024
1 parent 4681f2b commit 6c7c5ca
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 7 deletions.
4 changes: 2 additions & 2 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import sbtcrossproject.CrossPlugin.autoImport.CrossType
import sbtcrossproject.CrossProject
import org.scalajs.sbtplugin.ScalaJSCrossVersion

val nlDependencyVersion = "6.4.0-c4dc02a"
val nlDependencyVersion = "6.4.0-489eab1"

val parserJsDependencyVersion = "0.4.0-c4dc02a"
val parserJsDependencyVersion = "0.4.0-489eab1"

val scalazVersion = "7.2.35"

Expand Down
21 changes: 20 additions & 1 deletion compiler/shared/src/main/scala/Optimizer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import
org.nlogo.core.{ prim, AstTransformer, ProcedureDefinition, ReporterApp, Statement, NetLogoCore, CommandBlock, ReporterBlock },
prim.{ _any, _const, _count, _createorderedturtles, _createturtles, _equal, _fd, _greaterthan, _hatch, _lessthan,
_neighbors, _neighbors4, _not, _notequal, _observervariable, _of, _oneof, _other, _patchat, _patches, _patchvariable,
_procedurevariable, _random, _sprout, _sum, _with }
_procedurevariable, _random, _sprout, _sum, _turtleson, _with }

// scalastyle:off number.of.methods
object Optimizer {
Expand Down Expand Up @@ -333,6 +333,24 @@ object Optimizer {
}
}

class _anyturtleson extends Reporter {
override def syntax: Syntax =
Syntax.reporterSyntax(right = List(Syntax.AgentsetType | Syntax.AgentType), ret = Syntax.BooleanType)
}

// _any(_turtleson) => _anyturtleson
object AnyTurtlesOnTransformer extends AstTransformer {
override def visitReporterApp(ra: ReporterApp): ReporterApp = {
ra match {
case ReporterApp(a: _any, Seq(ReporterApp(_: _turtleson, turtlesonArgs, _)), _) =>
val r = new _anyturtleson
r.token = a.token
ra.copy(reporter = r, args = turtlesonArgs)
case _ => super.visitReporterApp(ra)
}
}
}

class NeighborTransformer extends AstTransformer {
def visitNeighbor(ra: ReporterApp, check: Reporter => Boolean, make: String => Reporter): ReporterApp = {
ra match {
Expand Down Expand Up @@ -495,6 +513,7 @@ object Optimizer {
AnyWith3Transformer .visitProcedureDefinition andThen
AnyWith4Transformer .visitProcedureDefinition andThen
AnyWith5Transformer .visitProcedureDefinition andThen
AnyTurtlesOnTransformer .visitProcedureDefinition andThen
OptimizeCountTransformer .visitProcedureDefinition andThen
RandomConstTransformer .visitProcedureDefinition
)(pd)
Expand Down
7 changes: 4 additions & 3 deletions compiler/shared/src/main/scala/SimplePrims.scala
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,10 @@ object SimplePrims {
PartialFunction.condOpt(r) {

// Agentset
case _: prim._any => "PrimChecks.agentset.any"
case _: prim._count => "PrimChecks.agentset.count"
case _: prim.etc._turtleson => "PrimChecks.agentset.turtlesOn"
case _: prim._any => "PrimChecks.agentset.any"
case _: prim._count => "PrimChecks.agentset.count"
case _: prim._turtleson => "PrimChecks.agentset.turtlesOn"
case _: Optimizer._anyturtleson => "PrimChecks.agentset.anyTurtlesOn"

// List / String
case _: prim.etc._empty => "PrimChecks.list.empty"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,13 @@ class AgentSetChecks
else
@prims.turtlesOnAgent(agentOrAgentset)

# (Agent | AgentSet) => Boolean
anyTurtlesOn: (agentOrAgentset) ->
if checks.isAgentSet(agentOrAgentset)
@prims.anyTurtlesOnAgentSet(agentOrAgentset)
else
@prims.anyTurtlesOnAgent(agentOrAgentset)

# [T <: (Array[Turtle]|Turtle|AbstractAgentSet[Turtle])] @ (Int, Int, T*) => TurtleSet
turtleSet: (sourceStart, sourceEnd, values...) ->
@setCreationArgsCheck('turtle-set', sourceStart, sourceEnd, types.Turtle, types.TurtleSet, values)
Expand Down
19 changes: 18 additions & 1 deletion engine/src/main/coffee/engine/prim/prims.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -235,10 +235,27 @@ module.exports =
turtlesOnAgent: (agent) ->
agent.turtlesHere()

# (Patch|Turtle) => Boolean
anyTurtlesOnAgent: (agent) ->
checks.isTurtle(agent) or !agent.turtlesHere().isEmpty()

# (PatchSet|TurtleSet) => TurtleSet
turtlesOnAgentSet: (agents) ->
turtles = flatMap((agent) -> agent.turtlesHere().toArray())(agents.iterator().toArray())
new TurtleSet(turtles, @_world)
new TurtleSet(Array.from(new Set(turtles)), @_world)

# (PatchSet|TurtleSet) => Boolean
anyTurtlesOnAgentSet: (agents) ->
if checks.isTurtleSet(agents)
return not agents.isEmpty()

# This is intentionally written as a loop for the `_anyturtleson` compiler optimization early exit -Jeremy B March
# 2024
for agent in agents
if not agent.turtlesHere().isEmpty()
return true

false

_hasWaited: false

Expand Down

0 comments on commit 6c7c5ca

Please sign in to comment.