The tentative name of the scripting language of Solace. It is somewhat of a misnomer, as although it has some strong LISP elements, it is also very strongly like sh, and has elements of Smalltalk thrown in to boot. It came to me in a dream after being a vague epiphany yesterday afternoon.

Although this is spammy and technically a cut-and-paste writeup, I am the original author of this, and although I don't normally put my Solace development diary into E2, for this I feel that I should make an exception:

I had the epiphany yesterday afternoon. I had the dream last night.

I present to you, the Solace scripting language, SoLISP. (Name pending.)

Actually, connoting that it's a LISP derivative, although accurate, is a bit demeaning to it. See, it's actually a combination of LISP and sh--

No, don't go away yet! Really! I have everything worked out, from the language to the execution model! It will^H^H^H^Hshould work! Really!

Okay. So what we have here is a cross between an imperative and a functional language. With a sprinkling of OO thrown in. I believe that EVERYTHING can be scripted in this, and that it can be made quite efficient (though for now I'm just going to implement a high-overhead pure-parsing interpreter).

The actual language is simple. There is a statement, in the form of

    cmd arg arg arg ...
and there is a compound statement in the form of
and there is (this is what makes it LISP-like) a nesting structure, which returns the result of executing what's inside (like sh's ` operator, except that it's nestable), and looks like:
The execution model is simple. The thing is parsed. As it's parsed, nesting structures are recursively executed, and the results of the parsing fill up a C++ vector, which is then executed. Er, let's try that again. No, let's not, I can't really explain it in English, just in C++ code, and explaining it in code defeats the purpose of saving it for later implementation. :)

Anyway. So when the statement is ready to be executed, first it's compared against the table of builtins. If it's not a builtin, then properties within its /scripts/ propdir are searched for, and if it's not found there then the parent object's are searched for, and if it's not found there then the parent object's parent object's /scripts/ propdir, and so forth. It sounds like there'll be a lot of overhead, but there won't; on a typical MUCK, you only have three layers of nesting most of the time (character, room, environment-room). There'll be four layers for a space where somone has setup global actions for all the rooms in a group, but I think that'll be unlikely, and all of the proptrees are going to be stored in nested hashmaps anyway, and so the power of the STL will keep our time-complexity to a minimum.

Anyway, so as an example of a simple script: the default 'say' command could be something like this:

echo You say, "{ARGS}". ; oecho says, "{ARGS}".

Oh, yeah. {VARNAME} means insert the value of a variable (like in sh except without the $). Variables are passed around in an execution environment to children (like in sh), though become separate entities (unlike in sh). There are, of course, some implicit variables such as ARGS and NAME and the like. Also, there will be both array-style access (i.e. {ARGS,0}), and there will be Scheme-like builtins for treating them as lists (i.e. (head {ARGS}), (tail {ARGS})). The insertion of the variable will NOT be evaluated; that's what the eval builtin is for. That is, like how in MPI-based MUCKs the MPI-testing function looks like:

in Solisp it looks like: Oh, and of course, there's a builtin for setting variables as well. Tentatively I'm calling it =; that is, to set the value of 'foo' to 'bar' you'd say:
    = foo bar
I'm doing that instead of 'set' because I'd rather use 'set' and 'get' for values in the proptree, i.e. or
    set /forms/current (head {ARGS})
So anyway, this is both functional and imperative. I'm not going to have any imperative looping or conditionals, because looping adds a lot more complexity to the parser and could be much better handled as a builtin, and functional and imperative conditionals would be almost identical and just work out to be syntactic sugar:
    if (eq {X} 0) 'This is a test' (eq {X} 1) 'only a test' 1 'thank you'
Oh, like in sh, '' and "" represent strings, with similar constraints (within '', {}s aren't expanded, and within "", they are). And that construct above represents the combination of 'if' and 'cond'. Its execution would look something like this: (yeah, I know, this defines 'if' in terms of 'if,' but if will be a builtin)
    if (true {ARGS,1}) (eval {ARGS,2}) 1 (if (tail (tail {ARGS}))
Let's see, what else... strings will be passed around atomically, there'll be a builtin 'split' which will split up a string, there'll be some sort of primitive for dealing with proptrees as a list (so for really hairy scripts you can put them into a proptree and do (eval (list /blah/blah/somehairything/))... There might or might not be lambda functions (probably not, since they don't seem all that useful to me)... Ummm, maybe I will have a simple for builtin:
    for i 1 (length {ARGS}) (oecho {ARGS,i})
BTW, a bit of explanation on 'echo' vs 'oecho': 'echo' says the args to whoever called the script, and 'oecho' says the character's name plus the args to everyone else in the room. Basically, 'oecho' is 'emote', for you MUDders, and 'osay' for you MPI programmers.

Oh, and I haven't mentioned how it was object-oriented, aside from the implicit inheritance thing. Many of the builtins will have handlers which are setup in propdirs. For example, when Foo pages Bar and Baz, the 'page' builtin sends a message of type 'page' to Bar and Baz, and then it gets intercepted by their page message handler, which is just a simple program which runs with SRC set to source and DEST set to the desination(s).

While we're at it, echo and oecho go through messages and thus can have handlers. Oh, and it'll output to the client something IRC-styled, such as:

    ECHO:This is only a test
    OECHO:Fluffy says, "Bite me."
    PAGE:[Foo] 07:23> Foo pages, "Hello!" (to you and Bar)
See, since there's still some client-side parsing going on. Also, we don't want stuff getting to the client in plaintext; otherwise it'd be way too easy to mess up the graphical clients by spoofing configuration changes and the like.

I've got a whole bunch of other stuff to think about on this, though, but I think that I've made a HUGE jump towards making ONSET a reality, at least...

Log in or register to write something here or to contact authors.