Using javascript for semantics specification

11 views
Skip to first unread message

p...@pi.net

unread,
Aug 12, 2011, 7:34:44 AM8/12/11
to UnQL
Perhaps it is possible to define the semantics of UnQL in terms of
javascript. Below a simple example that I hope to elaborate over the
next few days.


/*
** Simple specification for UnQL semantics in javascript
*/
var global = {};

function create_col(collection)
{
if( !global[collection] ) {
var col = {rowid:0};
global[collection] = col;
}
}

function do_insert(collection, expr)
{
var __doc__ = JSON.parse(expr);
var col = global[collection];
col[col.rowid++] = (JSON.stringify(__doc__));
}

function do_delete(collection, expr)
{
var col = global[collection];
for(var i in col) {
if( i==='rowid' ) continue;
var __doc__ = JSON.parse(col[i]);
eval('var '+collection+' = __doc__;');
if( expr && !eval(expr) ) continue;
delete col[i];
}
}

function do_update(collection, property, expr1, expr2, expr3)
{
var col = global[collection];
var updated = false;
for(var i in col ) {
var __doc__ = JSON.parse(col[i]);
eval('var '+collection+' = __doc__');
if( expr2 && !eval(expr2) ) continue;
updated = true;
eval( property+' = '+expr1 );
col[i] = JSON.stringify(__doc__);
}
if( !updated ) {
__doc__ = JSON.parse(expr3);
col[col.rowid++] = (JSON.stringify(__doc__));
}
}

function do_select(collection, expr1, expr2)
{
var __result__ = {};
var __rowid__ = 0;
var col = global[collection];
for(var i in col ) {
if( i==='rowid' ) continue;
var __doc__ = JSON.parse(col[i]);
eval('var '+collection+' = __doc__');
if( expr2 && !eval(expr2) ) continue;
if( expr1 ) {
__result__[__rowid__++] = JSON.stringify(eval(expr1));
}
else {
__result__[__rowid__++] = __doc__ ;
}
}
return __result__;
}

/*
** Worked example
*/

// CREATE COLLECTION abc;
create_col('abc');

// SELECT FROM abc;
document.write(JSON.stringify(do_select('abc', null, null))+'<br>');

// INSERT INTO abc VALUE {x:1, y:"a"}; etc.
do_insert('abc', '{"x":1, "y":"a"}' );
do_insert('abc', '{"x":2, "y":"b"}' );
do_insert('abc', '{"x":3, "y":"c"}' );
do_insert('abc', '{"x":4, "y":"d"}' );
do_insert('abc', '{"x":5, "y":"e"}' );

// SELECT FROM abc;
document.write(JSON.stringify(do_select('abc', null, null))+'<br>');
// SELECT FROM abc WHERE abc.y=="e";
document.write(JSON.stringify(do_select('abc', null, 'abc.y=="e"'))
+'<br>');
// SELECT abc.x FROM abc WHERE abc.y=="e";
document.write(JSON.stringify(do_select('abc', 'abc.x', 'abc.y=="e"'))
+'<br>');

// DELETE FROM abc WHERE abc.x<4
do_delete('abc', 'abc.x<4');

document.write(JSON.stringify(do_select('abc', null, null))+'<br>');
document.write(JSON.stringify(do_select('abc', null, 'abc.y=="d"'))
+'<br>');

// UPDATE abc SET abc.y = "k" WHERE abc.x==5;
do_update('abc', 'abc.y', '"k"', 'abc.x==5', null);

document.write(JSON.stringify(do_select('abc', null, null))+'<br>');
document.write(JSON.stringify(do_select('abc', null, 'abc.x=="5"'))
+'<br>');

// UPDATE abc SET abc.y = "k" WHERE abc.x==7 ELSE INSERT {"x":7,
"y":"z"};
do_update('abc', 'abc.y', '"k"', 'abc.x==7', '{"x":7, "y":"z"}');
// UPDATE abc SET abc.y = "m" WHERE abc.x==4 ELSE INSERT {"x":7,
"y":"z"};
do_update('abc', 'abc.y', '"m"', 'abc.x==4', '{"x":8, "y":"z"}');

document.write(JSON.stringify(do_select('abc', null, null))+'<br>');

/*
** Expected output
*/

{}
{"0":{"x":1,"y":"a"},"1":{"x":2,"y":"b"},"2":{"x":3,"y":"c"},"3":{"x":
4,"y":"d"},"4":{"x":5,"y":"e"}}
{"0":{"x":5,"y":"e"}}
{"0":"5"}
{"0":{"x":4,"y":"d"},"1":{"x":5,"y":"e"}}
{"0":{"x":4,"y":"d"}}
{"0":{"x":4,"y":"d"},"1":{"x":5,"y":"k"}}
{"0":{"x":5,"y":"k"}}
{"0":{"x":4,"y":"m"},"1":{"x":5,"y":"k"},"2":{"x":7,"y":"z"}}

Benjamin Young

unread,
Aug 15, 2011, 10:11:50 AM8/15/11
to un...@googlegroups.com
This is a great start! What do you think about mapping these functions
to IndexedDB for use in newer browsers?
http://www.w3.org/TR/IndexedDB/
https://developer.mozilla.org/en/indexeddb

It'd be great to get an in-browser experimentation suite online.

Thanks again for posting this,
Benjamin

On Fri Aug 12 07:34:44 2011, p...@pi.net wrote:
> Perhaps it is possible to define the semantics of UnQL in terms of
> javascript. Below a simple example that I hope to elaborate over the
> next few days.
>
>
> /*
> ** Simple specification for UnQL semantics in javascript
> */
> var global = {};
>
> function create_col(collection)
> {
> if( !global[collection] ) {
> var col = {rowid:0};
> global[collection] = col;
> }
> }
>
> function do_insert(collection, expr)
> {
> var __doc__ = JSON.parse(expr);
> var col = global[collection];
> col[col.rowid++] = (JSON.stringify(__doc__));
> }
>
> function do_delete(collection, expr)
> {
> var col = global[collection];
> for(var i in col) {
> if( i==='rowid' ) continue;
> var __doc__ = JSON.parse(col[i]);
> eval('var '+collection+' = __doc__;');

> if( expr&& !eval(expr) ) continue;


> delete col[i];
> }
> }
>
> function do_update(collection, property, expr1, expr2, expr3)
> {
> var col = global[collection];
> var updated = false;
> for(var i in col ) {
> var __doc__ = JSON.parse(col[i]);
> eval('var '+collection+' = __doc__');

> if( expr2&& !eval(expr2) ) continue;


> updated = true;
> eval( property+' = '+expr1 );
> col[i] = JSON.stringify(__doc__);
> }
> if( !updated ) {
> __doc__ = JSON.parse(expr3);
> col[col.rowid++] = (JSON.stringify(__doc__));
> }
> }
>
> function do_select(collection, expr1, expr2)
> {
> var __result__ = {};
> var __rowid__ = 0;
> var col = global[collection];
> for(var i in col ) {
> if( i==='rowid' ) continue;
> var __doc__ = JSON.parse(col[i]);
> eval('var '+collection+' = __doc__');

> if( expr2&& !eval(expr2) ) continue;

p...@pi.net

unread,
Aug 15, 2011, 5:31:57 PM8/15/11
to UnQL
On Aug 15, 4:11 pm, Benjamin Young <benja...@couchbase.com> wrote:
> This is a great start! What do you think about mapping these functions
> to IndexedDB for use in newer browsers?http://www.w3.org/TR/IndexedDB/https://developer.mozilla.org/en/indexeddb
>
> It'd be great to get an in-browser experimentation suite online.

For now I'm happy to store the data in an object or array. For the
purposes of explaining semantics it is perhaps better to stick to ecma
3rd edition stuff, as that is what everybody knows and understands.
Even using that it should be possible to make a 1000...2000 line in-
browser experimentation implementation.

Currently looking at a lexer/parser and at the select 'pipeline' for a
more serious implementation of SELECT. The lexer already brings
questions about the spec:
- are keywords lowercase, uppercase or case insensitive? (javascript:
lowercase)
- are identifier alphanumeric characters only ascii a-z and A-Z, or
are other scripts (e.g. Greek alpha-omega) included? (javascript 5th
edition: its the full utf set; same for whitespace)
- why are integers 64 bit at least? (javascript: all numbers are ieee
double, which only has 53 bit precision)

For now I'll go with lowercase keywords, ascii alphanumeric &
whitespace and 53 bit integers: my goal is to have simple code
explaining/clarifying UnQL semantics, nothing more.

Paul
Reply all
Reply to author
Forward
0 new messages