Table of Contents
HopScript Syntax
HopScript extends EcmaScript 5 syntax with the following additional constructs:
- service definitions and declarations;
~
-expressions and$
-expressions;- embedded HTML syntax.
The formal syntax is defined by:
Services
Services share most of their syntax with functions, with two notable differences:
- services are introduced with the
service
keyword; - services arguments may be named using the JavaScript object literal syntax.
<ServiceDeclaration> →
service <Identifier> ( <FormalParameterListopt> )
{ <FunctionBody> }
<ServiceExpression> →
| <ServiceDeclaration>
| service ( <FormalParameterListopt> )
{ <FunctionBody> }
<ServiceImport> → service <Identier> ()
Example
syntax/syntax.js
// service declaration with standard formal arguments
service add( x, y ) {
console.log( 'add - x: %s (%s), y: %s (%s)', x, typeof( x ), y, typeof( y ) );
return x + y;
}
function handleResult( result ) {
console.log( 'add returned: %s (%s)', result, typeof( result ) );
}
add( 2, 3 ).post( handleResult );
// add - x: 2 (number), y: 3 (number)
// add returned: 5 (number)
add( 2 ).post( handleResult );
// add - x: 2 (number), y: undefined (undefined)
// add returned: NaN (number)
add( 'foo', 'bar' ).post( handleResult );
// add - x: foo (string), y: bar (string)
// add returned: foobar (string)
add( 7, ' is a prime number').post( handleResult );
// add -x: 7 (number), y: is a prime number (string)
// add returned: 7 is a prime number (string)
service list() {
console.log( arguments ); // arguments is defined like in JavaScript functions
}
list().post(); // {}
list( 'foo', 'bar' ).post(); // { '0': 'foo', '1': 'bar' };
// service declaration with named formal arguments and default values
var scale = 100;
service figure( o ) {
var x = o && ("x" in o) ? o.x : 0;
var y = o && ("y" in o) ? o.y : 0;
var w = o && ("w" in o) ? o.w : 2 * scale;
var h = o && ("h" in o) ? o.h : scale;
var r = o && ("r" in o) ? o.r : 20;
var shape = o && ("shape" in o) ? o.shape : "rectangle";
switch (shape) {
case 'square': return { x: x, y: y, w: w, shape: shape };
case 'rectangle': return {x: x, y: y, w: w, h: h, shape: shape };
case 'circle': return { x: x, y:y, r: r, shape: shape };
default: return { x: x, y: y, shape: 'point' };
};
}
figure( { w: 200, shape: 'rectangle' } ).post( console.log );
// { shape: 'rectangle', x: 0, y: 0, w: 200, h: 100 }
figure( { x: 40, y: 50, shape: 'square' } ).post( console.log );
Tilde
HopScript client-side programs are values created by server-side computations.
They have a dedicated syntax: the ~
-expression. Server-side
values can be injected a ~
-expression using the $
-expressions.
<Expression> → ... | <~-Expression> | <$-Expression>
<~-Expression> → { <Expression> }
<$-Expression> → { <Expression> }
HTML
HopScript supports two syntaxes for creating server side HTML values. The first
one is plain HTML syntax extended with ~
- and $
-expressions. The second one
is an extension of JavaScript literal objects.
<CallExpression> → ... | <HtmlExpression> | <TagExpression>
<HtmlExpression> →
| < <Tag> <TagAttributes> > <HtmlChildren> </ <Tag> >
| < <Tag> />
<TagExpression> →
< <Tag> > { <TagArguments> }
| < <Tag> > { <TagArguments> } </ <Tag> >
<Tag> →
<Identifier>
| <Identifier> . <Tag>
<TagAttributes> →
| <TagName>
| <TagName> = <TagValue>
<TagName> → [^ =]+
<TagValue> → " [^"]* "
| <~-Expression>
| <$-Expression>
<HtmlChildren> →
<string>
| <boolean>
| <number>
| <date>
| <$-Expression>
| <~-Expression>
| <HtmlExpression>
<TagArguments> →
| <TagProperties>
| <TagElements>
| <TagProperties> , <TagElements>
<TagProperties> →
| <TagProperty>
| <TagProperty> , <TagProperties>
<TagProperty> →
<PropertyName> : <AssignmentExpression>
<TagElements> →
| <Expression>
| <Expression> , <TagElements>
Example
syntax/syntax.js
figure( { x: 40, y: 50, shape: 'square' } ).post( console.log );
// { x: 40, y: 50, w: 200, shape: 'square' }
figure( { shape: 'circle', y: 25 } ).post( console.log );
// { x: 0, y: 25, r: 20, shape: 'circle' }
// a service that returns plain HTML
service hello() {
return <html> <h1> Hello </h1> </html>;
}
// a service that returns an HTML element computed on the server side
var messages = { 'alice': 5, 'bob': 3 } // a database
service pendingMessages( name ) {
var numMessages = messages[ name ] || 0;
return <div> Hello ${name}, ${numMessages} messages </div>
}
// a complex service that combines server and client code
service syntax() {
var info = <div/>;
var input = <input size="10"/>;
var button = <button onclick=~{
var name = ${input}.value;
${pendingMessages}( name ).post( function( htmlElement ) {
${info}.appendChild( htmlElement );
});
}> login </button>;
return <html>
<div> Enter your name (alice, bob, whoever )
${input}
${button}
</div>
${info}
</html>;
}