How would I write an application which is a Clojure REPL? - clojure

I'd like to make an application available in the form of a Clojure REPL. Ie. something the user runs from the terminal and has a full Clojure REPL with a bunch of extra functionality included as Clojure functions.
I want the whole thing to live in a stand-alone JAR and not depend on the user already having Clojure installed or knowing how to install Clojure or import extra libraries. The whole thing should just be there when run.
Is there a straightforward way to make this? Ie. reusing the existing Clojure REPL code?

All you have to do is to run the clojure.main/repl in your own main.
The docs explain the entry points you have:
"Generic, reusable, read-eval-print loop. By default, reads from *in*,
writes to *out*, and prints exception summaries to *err*. If you use the
default :read hook, *in* must either be an instance of
LineNumberingPushbackReader or duplicate its behavior of both supporting
.unread and collapsing CR, LF, and CRLF into a single \\newline. Options
are sequential keyword-value pairs. Available options and their defaults:
- :init, function of no arguments, initialization hook called with
bindings for set!-able vars in place.
default: #()
- :need-prompt, function of no arguments, called before each
read-eval-print except the first, the user will be prompted if it
returns true.
default: (if (instance? LineNumberingPushbackReader *in*)
#(.atLineStart *in*)
#(identity true))
- :prompt, function of no arguments, prompts for more input.
default: repl-prompt
- :flush, function of no arguments, flushes output
default: flush
- :read, function of two arguments, reads from *in*:
- returns its first argument to request a fresh prompt
- depending on need-prompt, this may cause the repl to prompt
before reading again
- returns its second argument to request an exit from the repl
- else returns the next object read from the input stream
default: repl-read
- :eval, function of one argument, returns the evaluation of its
argument
default: eval
- :print, function of one argument, prints its argument to the output
default: prn
- :caught, function of one argument, a throwable, called when
read, eval, or print throws an exception or error
default: repl-caught"
Common things to do here:
:init: add your own setup for the REPL to use. E.g. use some libraries
:prompt: display a differnt "state" than the ns
:print: use a pretty printer of some kind
It's worth mentioning, that every program you build (e.g. uberjaring), that contains the clojure.main (e.g. the clojure-$VERSION.jar) can run the REPL from that uberjar so you can run differn main:s from there.
Self-advertisement: If you need further inspiration, these are "modified" REPLs I have done in the past:
REST-REPL: Add stateful URL navigation and tooling for consuming JSON/XML APIs
WREPL: Use integrant to have a module based composition for the REPL

Related

Lazy evaluation of Lauterbach macro - is it possible?

I'm currently writing some kind of a "skeleton" for tests to be performed using Lauterbach scripts.
In this skeleton I want to have a part in which all test specific definitions shall be done, e.g. functions to set breaks on, variables to be altered etc. This part shall be just near the top of the script file, so that other users do not have to go through the complete script file, changing values here and there.
Some of the variables that'll be used are defined function-local within the C-code to be tested. So, these become available to the Lauterbach script only once the scope of that function has been entered - which is deeply within the skeleton script code.
Is there a way to define a macro for these variables just way before the scope has been entered?
Let's give some example structure:
LOCAL &funcToTest // the function we want to test
LOCAL &varToBeSet // a variable within the function we want to alter
LOCAL &valueToBeSet // the value we want to set &varToBeSet to
... // some more definitions here
&funcToTest=someFunc
&varToBeSet=status
&valueToBeSet=1
... // some test code following here that sets up log files, screen areas
... // start the program to be tested etc.
IF (Register(PC)==ADDRESS.OFFSET(&funcToTest))
(
// OK - we've hit the breakpoint inside the function to test
... // Run to some point where we can set the local variable
Var.Set &varToBeSet=&valueToBeSet
... // Go on with the program and see what happens - this will be logged
)
The problem is that Lauterbach complains at the line &varToBeSet=status
with Symbol not found in this context - which is correct, because it is a local variable.
Looking at the symbols via View->Symbols->SymbolsTreeView (or by giving the command Symbol.List.Tree) I can find the symbol (in this particular case found under the node some_module.some_function.status). Clicking on it gives the information in the TRACE32 status status line \\some_app\some_module\some_func\status with type (auto STATUS), scope local, location stack.
Changing my script to read &varToBeSet=\\some_app\some_module\some_func\status instead of &varToBeSet=status, however, does not help much. In this case Lauterbach complains with no access to that symbol.
Is there a way, I can delay evaluation of the macro to some point where it is actually used instead of having it evaluated when it is defined?
Use quotes:
&varToBeSet="\\some_app\some_module\some_func\status"

Make a call in Lua, on a potentially not exposed Function in tolua++

I have a Lua script that uses some functions of my C++ application.
I use this script with 2 different C++ application, and I would like to be able to protect a call for not being bound through tolua.
For example:
- Let's say that I have two C++ applications: MyApp1 and MyApp2
- I made a wrapper of MyApp1 with tolua++ and I call one of its functions like this in a Lua script:
MyApp1:MyFunc()
Now I use this same script with MyApp2, that doesn't have any tolua++ binding of this type.
And I then get an error of this type:
[string "MyApp2.lua"]:157: attempt to index global 'MyApp1' (a nil value)
So I would like Lua not to send me an error when calling this method.
I tried to use:
pcall( MyApp1:MyFunc() )
But the script keeps on crashing on this line.
if MyApp1 then
MyApp1:MyFunc()
end
if MyApp1 then
MyApp1:MyFunc()
end
Above will work, but isn't it cleaner to separate application dependent and independent scripts? That way you woudn't have to worry about it.

Lua preserving global values

I use Lua for my game engine logic. My main game loop is not done in Lua. Only special nodes in my scene hierarchy have Lua scripts attached. These scripts are executed every frame. The problem I face is that I need to keep global variable values from one frame to another.
My temporary solution looks like this:
finish = useBool("finish", false)
timer = useInt("timer", 0)
showTimer = useBool("showTimer", true)
startTimer = useInt("startTimer", 0)
play0 = useBool("play0", false)
play1 = useBool("play1", false)
play2 = useBool("play2", false)
play3 = useBool("play3", false)
delta = useInt("delta", 0)
gameOverTime = useInt("gameOverTime", 5000)
finishTime = useInt("finishTime", 5000)
checkPoint = useInt("checkPoint", 255)
<...> Game logic <...>
setInt("message", message);
setInt("checkPoint", checkPoint)
setInt("finishTime", finishTime)
setInt("gameOverTime", gameOverTime)
setInt("timer", timer)
setBool("play3", play3)
setBool("play2", play2)
setBool("play1", play1)
setBool("play0", play0)
setInt("startTimer", startTimer)
setBool("showTimer", showTimer)
setInt("timer", timer)
setBool("finish", finish);
I call special methods that retrieve global variables from hash maps in C++ at the beginning and I set them again at the end of the script.
Is there a way to do this implicitly?
Is it a bad design to use Lua not as the main game loop?
Well, while there is nothing technically wrong with your solution, you might start to notice some performance issues if you end up with a lot of global variables (something you should, in general, avoid).
With that said, there is room for improvement. For example:
At the beginning of the script, check if your global variable is nil. If it is, then you can initialize it, if not, this is probably not the first time you're running the script, so leave it unmodified. But that means a lot of pesky if-else statements, which one can easily forget about. We can do better!
I would recommend looking at Chapter 14: The Environment, from the Programming in Lua book. Here's a quick quote from the intro:
Lua keeps all its global variables in a regular table, called the environment. ... The other (actually the main) advantage is that we can manipulate this table as any other table. To facilitate such manipulations, Lua stores the environment itself in a global variable _G. (Yes, _G._G is equal to _G.)
Since _G is a table, it also has a metatable, so you can define __index and __newindex metamethods to handle access to and creation of global variables. You can find examples of this in section 14.2. Go read the whole chapter, it's not that long (if you're unfamiliar with metamethods and metatables, also look through chapter 13 - this is where Lua really shines in terms of flexibility).
Now that we've covered the trivial and normal methods, let's look at the overkill end of the spectrum. As an example I'll look at Unity's approach to scripting. A Unity javascript usually defines variables, functions, and types. Any variables defined outside of the scope of methods or types are persisted between frames because the script itself is not executed every frame. Instead, they let the script define functions and call the functions at the appropriate time. So if you want something executed every frame - you put it in the Update function. Every script can define it's own Update function because it has it's own scope. So every frame the scripting engine goes through all objects, checks if the script's scope has an Update method and calls it.
Back to Lua - a solution like this would involve creating separate environments for each object/script/whatever your node is. Then, instead of executing the script attached to your node every frame, your main loop will go through all the nodes and run a function inside of their environment. You can also switch environments, so you can set the global environment to your node's env before executing it, and then switch back when you're done. This allows your scripts to use globals as they see fit, have them persisted between frames and excludes the possibility of name collisions or global namespace pollution. Additionally you can use metamethods to nest the node's environment inside the actual global environment or inside an API environment with helper methods (basically, if __index does not find something it looks it up in a parent).

Using Lua to define NPC behaviour in a C++ game engine

I'm working on a game engine in C++ using Lua for NPC behaviour. I ran into some problems during the design.
For everything that needs more than one frame for execution I wanted to use a linked list of processes (which are C++ classes). So this:
goto(point_a)
say("Oh dear, this lawn looks really scruffy!")
mowLawn()
would create a GotoProcess object, which would have a pointer to a SayProcess object, which would have a pointer to a MowLawnProcess object. These objects would be created instantly when the NPC is spawned, no further scripting needed.
The first of these objects will be updated each frame. When it's finished, it will be deleted and the next one will be used for updating.
I extended this model by a ParallelProcess which would contain multiple processes that are updated simultaneously.
I found some serious problems. Look at this example: I want a character to walk to point_a and then go berserk and just attack anybody who comes near. The script would look like that:
goto(point_a)
while true do
character = getNearestCharacterId()
attack(character)
end
That wouldn't work at all with my design. First of all, the character variable would be set at the beginning, when the character hasn't even started walking to point_a. Then, then script would continue adding AttackProcesses forever due to the while loop.
I could implement a WhileProcess for the loop and evaluate the script line by line. I doubt this would increase readability of the code though.
Is there another common approach I didn't think of to tackle this problem?
I think the approach you give loses a lot of the advantages of using a scripting language. It will break with conditionals as well as loops.
With coroutines all you really need to do is:
npc_behaviour = coroutine.create(
function()
goto(point_a)
coroutine.yield()
say("Oh dear, this lawn looks really scruffy!")
coroutine.yield()
mowLawn()
coroutine.yield()
end
)
goto, say and mowLawn return immediately but initiate the action in C++. Once C++ completes those actions it calls coroutine.resume(npc_behaviour)
To avoid all the yields you can hide them inside the goto etc. functions, or do what I do which is have a waitFor function like:
function waitFor(id)
while activeEvents[id] ~= nil do
coroutine.yield()
end
end
activeEvents is just a Lua table which keeps track of all the things which are currently in progress - so a goto will add an ID to the table when it starts, and remove it when it finishes, and then every time an action finishes, all coroutines are activated to check if the action they're waiting for is finished.
Have you looked at Finite State Machines ? If I were you I wouldn't use a linked list but a stack. I think the end result is the same.
stack:push(action:new(goto, character, point_a))
stack:push(action:new(say, character, "Oh dear, this lawn was stomped by a mammoth!"))
stack:push(action:new(mowLawn, character))
Executing the actions sequentially would give something like :
while stack.count > 0 do -- do all actions in the stack
action = stack:peek() -- gets the action on top of the stack
while action.over ~= true do -- continue action until it is done
action:execute() -- execute is what the action actually does
end
stack:pop() -- action over, remove it and proceed to next one
end
The goto and other functions would look like this :
function goto(action, character, point)
-- INSTANT MOVE YEAH
character.x = point.x
character.y = point.y
action.over = true -- set the overlying action to be over
end
function attack(action, character, target)
-- INSTANT DEATH WOOHOO
target.hp = 0
action.over = true -- attack is a punctual action
end
function berserk(action, character)
attack(action, character, getNearestCharacterId()) -- Call the underlying attack
action.over = false -- but don't set action as done !
end
So whenever you stack:push(action:new(berserk, character)) it will loop on attacking a different target every time.
I also made you a stack and action implementation in object lua here. Haven't tried it. May be bugged like hell. Good luck with your game !
I don't know the reasons behind you design, and there might be simpler / more idiomatic ways to it.
However, would writing a custom "loop" process that would somehow take a function as it's argument do the trick ?
goto(point_a)
your_loop(function ()
character = getNearestCharacterId()
attack(character)
end)
Since Lua has closures (see here in the manual), the function could be attached to your 'LoopProcess', and you call this same function at each frame. You would probably have to implement your LoopProcess so that that it's never removed from the process list ...
If you want your loop to be able to stop, it's a bit more complicated ; you would have to pass another function containing the test logic (and again, you LoopProcess would have to call this every frame, or something).
Hoping I understood your problem ...

Can I clean the repl?

I have played with a lot of code in a repl console, how can I clear it? I would like a fresh one without restarting it. Can that be done?
If you want to clear the current namespace of all temporary variables and functions you declared you can use this one liner (or make a function of it) :
(map #(ns-unmap *ns* %) (keys (ns-interns *ns*)))
or
(ns myutil)
(defn ns-clean
"Remove all internal mappings from a given name space or the current one if no parameter given."
([] (ns-clean *ns*))
([ns] (map #(ns-unmap ns %) (keys (ns-interns ns)))))
(ns mytest)
... make loads of junk ...
(myutil/ns-clean)
... great!!! I can now make all new junk ...
It does not claim to give you a squeaky clean namespace, just one with less of the junk which usually accumulates in a typical repl session.
Use with caution : do not pull the rug from under your feet!
If you are running the repl through a terminal window (eg: Terminal.app on MacOS or xterm/aterm/urxvt etc on linux) then you can type Control-L and it should clear the terminal window and give you a new repl prompt. However all macros/atoms you previously defined are still going to be in memory, so this is just a "Cosmetic" clear.
In EMACS/slime REPLs
C-c C-o clears the last output (in case you've typed something that gave a very long answer)
C-c M-o clears the whole thing
In GNOME terminals, you've got a menu option Terminal/Reset and Clear
The shorcut to clean the whole buffer : C-u C-c C-o
The shortcut to clean the last output : C-c C-o
Note, the old way was : C-c M-o
Also, cider-repl-clear-buffer (which is bound to C-ENTER s-c on my machine)
If you are using Emacs + nREPL, you can either:
Run Mx nrepl-clear-buffer or
Run Cc Mo
If the key binding is not enabled, run Mxnrepl-interaction-mode to enable it. You can find other useful shortcuts in nrepl.el and/or customize the key bindings to fit your needs.
Note: you can find all nREPL's key bindings in your system by running M-x v nrepl-mode-map and following the nrepl.el link.
I use the Emacs command cider-repl-clear-buffer via M-x. One might also use cider-repl-clear-output with a prefix argument: C-u C-c C-o.
It depends what you mean by 'clean'. To remove all namespaces within a 'package' you can use:
(mapv remove-ns
(map symbol
(filter #(.startsWith % "org.mycompany")
(map str (all-ns)))))
For users of the Cursive IDE plugin for IntelliJ IDEA who end up here, like me:
You can "cosmetically" clear the REPL (keeping your def'd symbols etc.) by clicking on this icon at the top of the REPL frame:
There's no default key binding for this, but you can easily add one by opening your preferences, navigating to Keymap > Plugins > Cursive, and adding a binding for "Clear output for current REPL".
Alternatively, you can right-click in the editor and access "Clear output for current REPL" via the REPL commands.