CLNL Interface
The NetLogo view interface using opengl. This is responsible for taking the current state of the enging and displaying it. Will not house any interface components.
export-view => image-data
image-data---A vector, pixel data as returned by opengls readPixels
export-view returns the current view in raw data of RGBA pixels.
Each pixel is made up of 4 bytes of data, which an be walked over. The number of pixels is the current width x height. Converting to some other image format is a matter of pulling that information out and putting it into whatever format you like.
This requires opengl to run, but can be used with xvfb in a headless mode.
initialize &key dims view buttons switches => result
```dims::= (:xmin xmin :xmax xmax :ymin ymin :ymax ymax :patch-size patch-size)
view::= (:left left :top top)
buttons::= button-def
switches::= switch-def``` button-def::= (:left left :top top :height height :width width :forever forever :display display)
switch-def::= (:left left :top top :width width :var var :display display :initial-value initial-value)
result---undefined xmin---An integer representing the minimum patch coord in X xmax---An integer representing the maximum patch coord in X ymin---An integer representing the minimum patch coord in Y ymax---An integer representing the maximum patch coord in Y patch-size---A double representing the size of the patches in pixels height---An integer representing height forever---A boolean representing the forever status left---An integer representing the left position top---An integer representing the top position width---An integer representing width var---A string representing the variable name display---A string representing display name initial-value---The initial value
This is where the initialization of the interface that sits behind the interface lives. From here, one can go into headless or running mode, but for certain things this interface will still need to act, and also allows for bringing up and taking down of visual elements.
run => result
result---undefined, should never get here
run runs the view in an external window.
This should be run inside another thread as it starts the glut main-loop. Closing this window will then cause the entire program to terminate.CLNL Lexer
The primary code responsible for tokenizing NetLogo code.
lex text => ast
text---Some NetLogo code ast---An ambigious ast that can later be parsed
lex lexes NetLogo code.
lex checks for some things, in as much as it can without knowing anything about some of the backgrounds of NetLogo. However, it does the first pass with as much as it can.CLNL Parser
All the code to convert the list of tokens coming from the lexer into an ast that can be transpiled later.
parse lexed-ast &optional dynamic-prims => ast
```dynamic-prims::= dynamic-prim
dynamic-prim::= (:name name :args args :infix infix :precedence precedence)
args::= arg```
lexed-ast---An ambigious ast ast---An unambigious ast that can be transpiled name---A symbol in the keyword package infix---Boolean denoting whether the prim is infix, defaulting to NIL precedence---A number, usually 10 for reporters, and 0 for commands arg---A list of symbols denoting the type of argument
parse takes a ambigious lexed-ast and converts it to an unambigious one.
dynamic-prims that are passed in are used to avoid compilation errors on things not statically defined by the NetLogo language, be they user defined procedures or generated primitives from breed declarations. name and precedence are required for all dynamic prims.
precedence is a number used to calculate the order of operations. Higher numbers have more precedence than lower ones. Generally all commands should have the lowest precedence, and all reporters should have 10 as the precedence.
The possible values for arg are :agentset, :boolean, :number, :command-block, :string, or t for wildcard. For optional arguments, arg can be a list of the form (arg :optional) where arg is one of the aforementioned values.
The need for a parser between the lexer and the transpiler is because NetLogo needs two passes to turn into something that can be used. This is the only entry point into this module, and should probably remain that way.
There's also a lot of error checking that the lexed-ast even makes sense, even though the lexer obviously thought it did.
Examples are too numerous and varied, but by inserting an output between the lexer and this code, a good idea of what goes on can be gotten.CLNL Transpiler
The transpiler is responsible for taking an ast and turning it into valid CL code targeting the nvm. Here is where start to care about commands versus reporters and ensuring that things are in the right place. The reason we wait until here is because we want to allow someone else to play with the AST before handing it off to us. For instance, the command center wants to add "show" to reporters, and the users dictate based on entry point whether they are expecting a command or a reporter. So monitors can say "hey, transpile this reporter" and we'll check to make sure it actually is.
Furthermore, the lisp code that any netlogo code would be transpiled to should use exported symbols, such that anyone writing NetLogo code in lisp could use the nvm in the same way that comes out of this transpiler All the code to convert the list of tokens coming from the lexer into an ast that can be transpiled later.
command-list-p parsed-ast => result
parsed-ast---An ast as returned by the parser result---A boolean
command-list-p returns whether the parsed-ast is a valid list of commands.
reporter-p parsed-ast => result
parsed-ast---An ast as returned by the parser result---A boolean
reporter-p returns whether the parsed-ast is a valid reporter.
transpile parsed-ast &optional dynamic-prims => ast
dynamic-prims::= dynamic-prim*
dynamic-prim::= (:name name :type type :macro macro :func func)
type::= :reporter | :command
parsed-ast---An ast as returned by the parser ast---An common lisp ast that can be actually run in a common lisp instance name---A symbol in the keyword package macro---A macro that will be called with the arguments ast func---A function that will be called with the transpiled arguments
transpile takes a unambigious parsed-ast and converts it to Common Lisp code. The parsed-ast must be either a list of commands, or a single reporter.
When a set of dynamic-prims is included, external language constructs can be also transpiled. The provided functions will be inserted into the returned ast with a call to funcALL. If :macro is included, instead of having a call to funcALL provided, the macro will be run at netlogo transpile time, with the arguments it should have specified to the parser. The result of that function call will then be dropped into the ast.
Calling eval on that code should work correctly as long as you have a running engine.CLNL Code Parser
A parser specifically for code from NetLogo models, that turns the lexed ast from an entire structured file into something more defined.
This is different from the general parser (in clnl-parser) in that it's made for parsing the code section of nlogo files, and so works outside of the constraints. In NetLogo, I believe this is analagous to the StructureParser, but I'm guessing there's weird overlap with other things.
breeds code-parsed-ast => breeds
breeds::= breed*
code-parsed-ast---An ast as created by clnl-code-parse:parse breed---A symbol interned in :keyword
Returns the breeds that get declared in the code.
globals code-parsed-ast => globals
globals::= global*
code-parsed-ast---An ast as created by clnl-code-parse:parse global---A symbol interned in :keyword
Returns the globals that get declared in the code.
parse lexed-ast &optional external-globals => ast, prims
lexed-ast---An ambigious ast external-globals---A list of symbols in keyword package ast---An unambigious ast that represents the code block of a model prims---Primitives that can be sent to the parser and transpiler
parse takes a ambigious lexed-ast and converts it to an unambigious one. It also returns the primitives that are defined in the code file, including ones generated from the external-globals, that can then be passed to both the parser and the transpiler.
external-globals is a list of symbols representing global variables that are not defined within the code. Normally these come from widgets defined in the model file, but could arguably come from elsewhere.
This parser, unlike CLNL-parse:parse, should not be fed into the transpiler.
Rather, the ast that's returned can be queried with other functions included in the CLNL-CODE-parseR package to tease out necessary information. Some of those things will involve code blocks that can then be transpiled.
patches-own-vars code-parsed-ast => patches-own-vars
patches-own-vars::= patches-own-var*
code-parsed-ast---An ast as created by clnl-code-parse:parse patches-own-var---A symbol interned in :keyword
Returns the turtles own variables that get declared in the code.
procedures code-parsed-ast => procedures
procedures::= procedure*
procedure::= (name body)
code-parsed-ast---An ast as created by clnl-code-parse:parse name---A symbol interned in :keyword body---A list of lexed forms
Returns the procedures that were defined in the code. These can then be translated into common lisp by using mapcar on the body, and set to some function defined by name
turtles-own-vars code-parsed-ast => turtles-own-vars
turtles-own-vars::= turtles-own-var*
code-parsed-ast---An ast as created by clnl-code-parse:parse turtles-own-var---A symbol interned in :keyword
CLNL Model
The representation, parsing, and serializing of NetLogo model files, including all of the sections, and subsections held within. This package houses not only the code to read and write .nlogo files, but also the living state of the model as clnl runs.
buttons model => button-defs
button-defs::= button-def*
button-def::= (:left left :top top :height height :width width :forever forever :display display)
model---A valid model left---An integer representing the left position top---An integer representing the top position height---An integer representing height width---An integer representing width forever---A boolean representing whether this button is a forever button display---A string representing display name
Returns button definitions that get declared in the buttons of the model. This is used to initialize the interface.
code model => code
model---A valid model code---The string representing the netlogo code in this model
Returns the code from the model.
default-model => model
model---an object representing the model
Returns the default startup model.
execute-button name &optional idx => result
name---the name of the button idx---the instance of the button, defaults to 0 result---undefined
Executes the code in the button referenced by name and idx.
name refers to the display name for the button, which is usually set by the model, but sometimes defaults to the code inside.
Because name is not guaranteed to be unique, idx is available as a specifier. The index is in the order that the buttons are loaded, and cannot be guaranteed to be stable from run to run.
forever-button-on name &optional idx => on
name---the name of the button idx---the instance of the button, defaults to 0 on---a boolean
Returns whether the button identified by name and idx is currently on.
name refers to the display name for the button, which is usually set by the model, but sometimes defaults to the code inside.
Because name is not guaranteed to be unique, idx is available as a specifier. The index is in the order that the buttons are loaded, and cannot be guaranteed to be stable from run to run.
interface model => interface
model---an object representing the model interface---a list of widgets for display
interface returns the widgets in model, used for display, or setting with SET-CURRENT-interface.
read-from-nlogo str => model
str---a readable stream model---an object representing the model
Takes a stream str, reads in a nlogo file, parses it, and then returns the model object.
set-callback callback => result
callback---a function that can take netlogo code result---undefined
Sets the means by which the interface can call arbitrary netlogo code.
set-current-interface interface => result
interface---a list of widgets for display result---undefined
Sets the currently running model to interface.
The widgets set here are comprised of the bare necessary to run the engine with or without an actual visual component.
sliders model => slider-defs
slider-defs::= slider-def*
slider-def::= (:left left :top top :width width :var var :display display :initial-value initial-value)
model---A valid model left---An integer representing the left position top---An integer representing the top position width---An integer representing width var---A symbole representing variable display---A string representing variable name initial-value---The initial value
Returns slider definitions that get declared in the sliders of the model. This is used to initialize the interface.
switches model => switch-defs
switch-defs::= switch-def*
switch-def::= (:left left :top top :width width :var var :display display :initial-value initial-value)
model---A valid model left---An integer representing the left position top---An integer representing the top position width---An integer representing width var---A symbole representing variable display---A string representing variable name initial-value---The initial value
Returns switch definitions that get declared in the switches of the model. This is used to initialize the interface.
textboxes model => textbox-defs
textbox-defs::= textbox-def*
textbox-def::= (:left left :top top :height height :width width :display display)
model---A valid model left---An integer representing the left position top---An integer representing the top position height---An integer representing height, in characters width---An integer representing width, in characters display---A string representing display name
Returns textbox definitions that get declared in the textboxes of the model. This is used to initialize the interface.
view model => view-def
view-def::= (:left left :top top)
model---A valid model left---An integer representing the left position top---An integer representing the top position
Returns the view definition that get declared in the view of the model. This is used to initialize the interface.
widget-globals model => globals
globals::= global*
global::= (name default)
model---A valid model name---A symbol interned in the keyworkd package default---The widget default value
Returns the globals that get declared in the model from widgets. They are interned in the keyword package package set for clnl, so that they can later be used for multiple purposes.
world-dimensions model => dims
dims::= (:xmin xmin :xmax xmax :ymin ymin :ymax ymax)
model---A valid model containing a view xmin---An integer representing the minimum patch coord in X xmax---An integer representing the maximum patch coord in X ymin---An integer representing the minimum patch coord in Y ymax---An integer representing the maximum patch coord in Y
Wrapper around mt19937.
mt19937 implements a merseinne twister that must be adapted a little in order to match the implementation in the main NetLogo codebase which tries to match how java.util.Random works. Turtles, all the way down.
export => random-state
random-state---A dump of the current random state
export dumps out the random state to be export world ready.
When NetLogo dumps out the current state of the engine, the state of the RNG also gets dumped out so that it can be reinitialized later. This accomplishes that.
This isn't really useful for regular use.
next-double &optional n => double
n---A double representing the upper bound double---A double
next-double returns the next randomly generated double.
It does so in a way that's in accordance with java.util.Random and the MerseinneTwisterFast that's in netLogo. It also advances the RnG and is bounded by n.
next-int n => int
n---An integer representing the upper bound int---An integer
next-int returns the next randomly generated integer.
It does so in a way that's in accordance with java.util.Random and the MerseinneTwisterFast that's in netLogo. It also advances the RnG and is bounded by n.
next-long n => long
n---A long representing the upper bound long---A long
next-long returns the next randomly generated long.
It does so in a way that's in accordance with java.util.Random and the MerseinneTwisterFast that's in netLogo. It also advances the RnG and is bounded by n.
set-seed => result
result---undefined
set-seed sets the seed on the RNG.