package org.nlogo.prim
class _breedvariable(name: String) extends nvm.Reporter {
def syntax = core.Syntax.reporterSyntax(...)
def toString = s"${super.toString}:$name"
def report(context: nvm.Context): AnyRef =
context.agent.getBreedVariable(name)
}
package org.nlogo.core
package prim
class _breedvariable(name: String) extends Reporter { // that's core.Reporter
def syntax = Syntax.reporterSyntax(...)
def toString = s"${super.toString}:$name"
}
package org.nlogo.prim
class _breedvariable(bv: core.prim._breedvariable) extends nvm.Reporter {
def report(context: nvm.Context): AnyRef =
context.agent.getBreedVariable(bv.name)
}
package org.nlogo.prim
object _breedvariable {
def apply(bv: core.prim._breedvariable) =
new _breedvariable(bv.name)
}
class _breedvariable(name: String) extends nvm.Reporter {
def report(context: nvm.Context): AnyRef =
context.agent.getBreedVariable(bv.name)
}
Until we reach Assembler, we'd have only the ASTs, containing instances of core.Command (inside ast.Statement) and core.Reporter (inside ast.ReporterApp).
Assembler would discard the ASTs and replace them with instances of nvm.Command and nvm.Reporter.
The mapping from the front end classes in core.prim to the back end classes in prim would be via reflection, I suppose. There could also be a big static map that did it, but we'd either have to hand-maintain it, or generate it. Generating it is just as ugly as reflection, and hand-maintenance sucks, so I'd lean towards reflection. It wouldn't be any worse than the old system, which does reflection on the class names stored in tokens.txt
.
since we're holding off until Assembler to instantiate the prim classes, we could do this:
package org.nlogo.prim
class _plus(arg0: nvm.Reporter, arg1: nvm.Reporter) {
def report(context: nvm.Context) =
arg0.reportDoubleValue + arg1.reportDoubleValue
}
which is a lot cleaner than the current grubby args
/arg0
/arg1
/... stuff.
We might want to add def args = Seq(arg0, Arg1) = ...
just so we can do things like print out the assembled code. Though I suppose reflection could accomplish the same thing.
I had been planning on redoing the front end of the compiler so that AST nodes didn't have Instruction objects (Commands and Reporters) attached to them anymore, but instead just a Syntax object and a string with the canonical name of the prim.
I ran into two fundamental difficulties:
- It's a radical change that was going to involve tearing up lots of code. It was going to be difficult to accomplish before April 30.
- We have too many primitives that can't easily be shoehorned into a
(String, Syntax)
representation - Other information we need to attach includes:
- breed names
- lvalues (a variable number or name)
- Not clear how to attach this stuff except by piling it into the string, or by resorting to a
Seq[Any]
type hack - Representing primitives with String instead of classes would cost us a lot of compile-type safety.
- If push comes to shove, maintaining module boundaries is more important than maximizing compile-time safety, but must we sacrifice one or the other?
Side note: for a while I also considered attaching the extra information as additional AST nodes, as we already do with the _reference
-Referenceable
-TypeReference
stuff for the diffuse
, downhill
, uphill
family of primitives, but it's too big a change, and I'm thinking it's actually a bad idea even if were feasible.