Difference between revisions of "LSL Protocol/ListMessage"

From Second Life Wiki
Jump to navigation Jump to search
(suggest a way of encoding lists, non-lists, non-results, verb-not-found, and partially evaluated Polish expressions)
 
m (<lsl> tag to <source>)
 
(5 intermediate revisions by 3 users not shown)
Line 11: Line 11:
We then work with results of any non-list type, also results of list type, also parameter lists that include lists as entries, also the results of verbs that return no results, also the result that is failing to make sense of an unintelligible unknown verb.
We then work with results of any non-list type, also results of list type, also parameter lists that include lists as entries, also the results of verbs that return no results, also the result that is failing to make sense of an unintelligible unknown verb.


I guess we want [[llMessageLinked]] to pass such things to [[link_message]], so that we can divide the work of interpretation across indefinitely many scripts.
I guess we want [[llMessageLinked]] to pass such interpreter things to [[link_message]], so that we can divide the work of interpretation across indefinitely many scripts.


I guess we want to invent some way of escaping such things: (a) some perfectly reversible way to encode such things as a list we can pass around a script, and (b) some perfectly reversible way of encoding a list as a string.
I guess we want to invent some way of escaping interpreter things, in three parts:
 
i) some way of losslessly encoding any string as a string without troublesome punctuation that makes the one string look like more strings, and
 
ii) some way of losslessly encoding any list as a string, and
 
iii) some way of losslessly encoding interpreter things as a list.
 
Answers for that dream include:
 
i) A scheme for losslessly encoding any string as a string that begins with "\"" and contains no troublesome punctuation may be "\"" + [[llEscapeURL]](string) + "\"".
 
ii) A scheme for losslessly encoding any list as a string may be to encode its strings and then [[llDumpList2String]] with a ", " separator.
 
iii) A scheme for losslessly encoding interpreter things (without source comments) as a list may be:


<pre>
<pre>
[] = unknown verb
[ ] = the result of a verb that returns no result
 
[ "<>" ] = the result of a verb that returns no result


[ 0... ] = float or integer result
[ 0... ] = float or integer result
[ "\"...\"" ] = key or string result, may be empty = encoded simply as "\"" + ([[lEscapeURL]](string) + "\""
[ "\"...\"" ] = key or string result, may be empty
[ "<...>" ] = rot or vector
[ "<...>" ] = rot or vector


[ "[", ..., "]" ] = list, may be empty
[ "[" "]" ] = empty list
[ "[", ..., "]" ] = non-empty list
 
[ verb "(", ..., ")" ] = verb applied to evaluated args = verb and list of zero or more args, maybe nested in the sense of args may be lists


[ "(", ..., ")" ] = partially evaluated Polish expression = list of verb with zero or more args, may be nested in the sense of args may be lists
["<>"] = the non-result of a meaningless verb
</pre>
</pre>
==Example==
Here's a first draft of an example of code that converts from string to call to result to string ...
<source lang="lsl2">
// http://wiki.secondlife.com/wiki/LSL_Protocol/ListMessage
string example1 = "llList2List([\"al%20ef\", \"bet\", \"gi%20mel\" ], 1, -2);";
list thePuts;
put(string message)
{
    list separators = [" ", ",", ";"];
    list spacers = ["(", ")", "[", "]"];
    list words = llParseString2List(message, separators, spacers);
    thePuts = words + "";
}
string get()
{
    string word = llList2String(thePuts, 0);
    thePuts = llDeleteSubList(thePuts, 0, 0);
    return word;
}
list getList()
{
    list words = [];
    get(); // "["
    @loop;
    if(thePuts != [])
    {
        string word = get();
        if(word != "]")
        {
            words += word;
            jump loop;
        }
    }
    return words;
}
string getString()
{
    string word = get();
    if (word == "\"\"") return "";
    return llUnescapeURL(llGetSubString(word, 1, -2));
}
list sendList(list results)
{
    return "[" + results + "]";
}
string sendString(string result)
{
    return "\"" + llEscapeURL(result) + "\"";
}
list sendVerbNotFound()
{
    return ["<>"];
}
string results2sendable(list results)
{
    integer resulted = llGetListLength(results);
    if (resulted == 0) // no result from meaningful verb
    {
        return "[]";
    }
    else if (resulted == 1) // meaningless verb or non-list result from meaningful verb
    {
        return llList2String(results, 0);
    }
    else if (resulted == 2) // empty list result from meaningful verb
    {
        return "[ ]";
    }
    else // if (3 <= resulted) // non-empty list result from meaningful verb
    {
        list middle = llList2List(results, 1, -2);
        return "[" + llDumpList2String(middle, ", ") + "]";
    }
}
list runnable2results(string message)
{
    put(message);
    string verb = get();
    get(); // "("
    if (verb == "llList2List")
    {
        return sendList(llList2List(getList(), (integer) get(), (integer) get()));
    }
    return sendVerbNotFound();
}
default
{
    state_entry()
    {
        string runnable = example1;
        llOwnerSay(results2sendable(runnable2results(runnable)));
    }
}
</source>

Latest revision as of 12:42, 25 January 2015

Back to Protocol page

List Message Protocol

(Proposed) (Draft, not implemented) (Open for comments)

When we solve problems like interpreting an LSL expression a la Chatbot, ...

We then work with results of any non-list type, also results of list type, also parameter lists that include lists as entries, also the results of verbs that return no results, also the result that is failing to make sense of an unintelligible unknown verb.

I guess we want llMessageLinked to pass such interpreter things to link_message, so that we can divide the work of interpretation across indefinitely many scripts.

I guess we want to invent some way of escaping interpreter things, in three parts:

i) some way of losslessly encoding any string as a string without troublesome punctuation that makes the one string look like more strings, and

ii) some way of losslessly encoding any list as a string, and

iii) some way of losslessly encoding interpreter things as a list.

Answers for that dream include:

i) A scheme for losslessly encoding any string as a string that begins with "\"" and contains no troublesome punctuation may be "\"" + llEscapeURL(string) + "\"".

ii) A scheme for losslessly encoding any list as a string may be to encode its strings and then llDumpList2String with a ", " separator.

iii) A scheme for losslessly encoding interpreter things (without source comments) as a list may be:

[ ] = the result of a verb that returns no result

[ 0... ] = float or integer result
[ "\"...\"" ] = key or string result, may be empty
[ "<...>" ] = rot or vector

[ "[" "]" ] = empty list
[ "[", ..., "]" ] = non-empty list

[ verb "(", ..., ")" ] = verb applied to evaluated args = verb and list of zero or more args, maybe nested in the sense of args may be lists

["<>"] = the non-result of a meaningless verb

Example

Here's a first draft of an example of code that converts from string to call to result to string ...

// http://wiki.secondlife.com/wiki/LSL_Protocol/ListMessage

string example1 = "llList2List([\"al%20ef\", \"bet\", \"gi%20mel\" ], 1, -2);";

list thePuts;

put(string message)
{
    list separators = [" ", ",", ";"];
    list spacers = ["(", ")", "[", "]"];
    list words = llParseString2List(message, separators, spacers);
    thePuts = words + "";
}

string get()
{
    string word = llList2String(thePuts, 0);
    thePuts = llDeleteSubList(thePuts, 0, 0);
    return word;
}

list getList()
{
    list words = [];
    get(); // "["
    @loop;
    if(thePuts != [])
    {
        string word = get();
        if(word != "]")
        {
            words += word;
            jump loop;
        }
    }
    return words;
}

string getString()
{
    string word = get();
    if (word == "\"\"") return "";
    return llUnescapeURL(llGetSubString(word, 1, -2));
}

list sendList(list results)
{
    return "[" + results + "]";
}

string sendString(string result)
{
    return "\"" + llEscapeURL(result) + "\"";
}

list sendVerbNotFound()
{
    return ["<>"];
}

string results2sendable(list results)
{
    integer resulted = llGetListLength(results);
    if (resulted == 0) // no result from meaningful verb
    {
        return "[]";
    }
    else if (resulted == 1) // meaningless verb or non-list result from meaningful verb
    {
        return llList2String(results, 0);
    }
    else if (resulted == 2) // empty list result from meaningful verb
    {
        return "[ ]";
    }
    else // if (3 <= resulted) // non-empty list result from meaningful verb
    {
        list middle = llList2List(results, 1, -2);
        return "[" + llDumpList2String(middle, ", ") + "]";
    }
}

list runnable2results(string message)
{
    put(message);
    string verb = get();
    get(); // "("
    if (verb == "llList2List")
    {
        return sendList(llList2List(getList(), (integer) get(), (integer) get()));
    }
    return sendVerbNotFound();
}

default
{
    state_entry()
    {
        string runnable = example1;
        llOwnerSay(results2sendable(runnable2results(runnable)));
    }
}