Dit hoofdstuk bespreekt de mogelijkheden van WMLScript (Wireless Markup Language Script). WMLScript maakt deel uit van de applicatielaag van WAP, en men kan het gebruiken om procedurele logica toe te voegen aan WML cards en decks. De taal is gebaseerd op ECMAScript, maar werd aangepast om betere ondersteuning te bieden voor toestellen met een lage bandbreedte, zoals mobiele telefoons.
Het Wireless Application Protocol (WAP) omvat WMLScript, een scripttaal die kan gebruikt worden met de Wireless Markup Language (WML) om intelligente diensten aan te bieden. WMLScript kan daarnaast ook als afzonderlijke tool gebruikt worden.
WMLScript biedt een oplossing voor de beperkingen van WML:
Het tekstuele formaat van de WMLScripttaal moet gecompileerd worden in een binair formaat vooraleer het kan worden geïnterpreteerd door de WMLScript bytecode interpreter. Een WMLScript encoder vertaalt één WMLScript compilatie-eenheid in WMLScript bytecode gebruik makend van een voorgeschreven formaat. Een WMLScript compilatie-eenheid is een eenheid die een aantal WMLScript functies bevat. De WMLScript compiler neemt zo’n eenheid als input, en genereert WMLScript bytecode als output.
WMLScript interpreter neemt de WMLScript bytecode als invoer en voert de gecodeerde functies uit zoals ze opgeroepen worden. Onderstaande figuur bevat de hoofdonderdelen met betrekking tot de WMLScript bytecode interpretatie.
We zien duidelijk dat op de figuur dat scripts die je zelf gecodeerd hebt, eerst in WMLScript bytecode moeten omgezet worden alvorens ze geïnterpreteerd kunnen worden. Let ook op de 4 elementen van informatie die bijgehouden worden en die de toestand (state) bepalen tijdens het proces.
De WMLScript interpreter kan gebruikt worden om functies aan te roepen en uit te voeren die in een compilatie-eenheid zitten onder de vorm van WMLScript bytecode. Elke functie specificeert het aantal parameters dat ze nodig heeft, en de instructies die nodig zijn om haar gedrag uit te drukken. Vandaar dat de aanroep van een WMLScript functie volgende zaken moet bevatten: de functie zelf, de argumenten en de compilatie-eenheid in dewelke de functie gedeclareerd werd. Wanneer de uitvoering normaal verloopt, zal de WMLScript interpreter de berekende waarde teruggeven aan de oproeper.
Het uitvoeren van een WMLScriptfunctie betekent dus dat men een functie in WMLScript bytecode gaat interpreteren. Terwijl de functie geïnterpreteerd wordt, zal de WMLScript interpreter volgende informatie bijhouden:
Hoewel het niet tot de scope van dit werk behoort om een volledige beschrijving te geven van WMLScript, kan de lezer in deze paragraaf toch een aantal kernbegrippen en elementen vinden die iedereen in staat stellen om eenvoudige WMLScripts te genereren. De concepten worden besproken die van praktisch nut zijn bij het ontwerpen van toepassingen voor WAP. De lezer die al enigszins vertrouwd is met een of andere scripttaal zal de analogie zeker moeten onderkennen.
Opnieuw kan in de bibliografie een aantal referenties gevonden worden naar extra informatie die de materie dieper uitspit.
De declaratie van een variabele gebeurt eenvoudigweg door het
var
element te gebruiken gevolgd door de naam van
de variabele. Het spreekt voor zich dat een variabele moet
gedeclareerd zijn voordat men deze kan gebruiken.
Bovendien is het ook zo dat een variabele enkel toegankelijk
is binnen de functie binnen dewelke deze werd gedeclareerd
(= local variabele).
var x; var size = 3;
De laatste syntax declareert een variabele (net zoals de bovenste drie), wat betekent dat de variabele vanaf dan bestaat en kan gebruikt worden, maar doet iets extra. Ze kent er meteen de waarde drie aan toe.
Net zoals de meeste scripttalen is ook WMLScript zwak getypeerd. Volgende variabelen zijn intern ondersteund: boolean, integer, floating-point en string. Aan dit rijtje werd een vijfde type toegevoegd, met name invalid. Belangrijk is wel dat deze datatypes intern ondersteund worden. De programmeur moet dus de types niet specificeren en elke variabele kan elke informatie bevatten op elk ogenblik. WMLScript zal proberen om automatisch tussen de verschillende types te converteren als dat nodig is.
var flag = true; // Boolean var number = 12; // Integer var temperature = 37.7; // Float number = "XII" // String var except = invalid // Invalid
WMLScript beschikt over verschillende manieren om een waarde toe te wijzen aan een variabele. De eenvoudigste manier is de normale toewijzing (=), maar er zijn ook toewijzingen met operaties.
Operator Operatie = Toewijzing. += Tel getallen op/voeg strings bijeen en wijs toe. -= Trek af en wijs toe. *= Vermenigvuldig en wijs toe. /= Deel en wijs toe. div= Gehele deling en toewijzing. %= Rest bij deling en toewijzing. &= Bitsgewijze AND en toewijzing. ^= Bitsgewijze XOR en toewijzing. |= Bitsgewijze OR en toewijzing.De logische AND operator evalueert de eerste operand en controleert het resultaat. Als het resultaat vals is, is het resultaat van de operatie vals en wordt de tweede operand niet meer gecontroleerd. Als de eerste operand waar is, zal het resultaat van de operatie afhangen van de evaluatie van de tweede operand. Is deze waar, dan is de operatie waar, is deze tweede operand vals dan is ook de operatie vals.
Deze opmerking kan volledig analoog voor de logische OR gemaakt worden.
WMLScript biedt dus ondersteuning voor het bijeenvoegen van strings (cf. string concatenation). De + en += operatoren, als ze gebruikt worden met strings als operand, realiseren deze functie. Andere operaties op strings worden ondersteund door een standaard String bibliotheek (zie paragraaf 3.5).
Bijvoorbeeld:
Var str = "Beginning" + "End" Var str = String.charAt(str,10); // chr = "E"
Dit voorbeeld voegt eerst de strings "Beginning" en "End" samen. De tweede regel is een functie (die in de standaardbibliotheek zit) die een teken op een bepaalde positie opvraagt. De concatenatie geeft als resultaat de string "BeginningEnd" en de tiende positie hieruit is inderdaad de letter E. De standaardfuncties omvatten trouwens niet alleen bewerkingen op strings. Een algemeen overzicht, zonder verdere uitleg, staat onder paragraaf 3.5.
Daarnaast zijn ook nog array operatoren, de komma-operator, de conditie-operator, de typeoff operator en de isvalid operator beschikbaar. Ze vallen echter buiten de scope van dit werk.
De komma-operator wordt gebruikt om het einde van een statement aan te geven.
Voor de resterende operatoren zijn opnieuw nuttige referenties beschikbaar in de bibliografie.
Een WMLScriptfunctie is een benoemd deel van de WMLScript compilatie-eenheid en kan aangeroepen worden om een bepaalde set van instructies uit te voeren en een waarde op te leveren.
Functiedeclaratie wordt gebruikt om de naam (Identifier) van een WMLScriptfunctie te declareren met zijn optionele parameters (FormalParameterList). Alle functies hebben volgende kenmerken:
De syntax voor een functiedeclaratie is:
FunctionDeclaration: Externopt function Identifier (FormalParameterListopt) Block;opt FormalParameterList: Identifier FormalParameterList, Identifier
Het optionele woord extern
kan gebruikt worden om aan te geven
dat de functie extern toegankelijk is. Externe functies kunnen dus van
buiten de compilatie-eenheid in dewelke ze gedefinieerd zijn, aangeroepen worden.
Identifier is de naam van de functie. FormalParameterList (optioneel) is
een lijst met namen van argumenten, gescheiden door een komma. Block
is dan de romp van de functie die wordt uitgevoerd wanneer de functie
is aangeroepen en de parameters geïnitialiseerd zijn door middel van
het doorgeven van argumenten.
Voorbeeld:
function calculateVAT(amount, VAT) { return amount*VAT; }; extern function testIt() { var purchase_amount = 20000; var total_amount = calculateVAT(purchase_amount, 1.21); };
De eerste functie calculatieVAT is een functie die twee invoerargumenten nodig heeft, amount en VAT. Worden deze aangebracht, dan levert die functie het bedrag inclusief BTW op. Immers, de return-statement is amount*VAT.
De tweede functie testIt maakt de gebruik van de functie. Ze definieert eerst een variabele purchase_amount en kent de waarde 2000 hieraan toe. Vervolgens roept ze de functie calculateVAT op, geeft de twee vereiste argumenten door en stopt het resultaat in de variabele total_amount.
De meegegeven argumenten, vereist voor de functie, staan tussen haakjes. Purchase_amount is een variabele, en 1.21 het VAT-percentage. Hier is geopteerd om dit percentage als constante te beschouwen.
Merk op dat de functie testIt geen argumenten vereist!
De manier waarop een functie wordt aangeroepen is afhankelijk van de plaats waar de opgeroepen functie werd gedeclareerd. We kunnen dan ook functies aanroepen op drie verschillende manier in WMLScript: de lokale en de externe functie-aanroep en het aanroepen van functies uit bibliotheken.
Deze functies (gedefinieerd binnen dezelfde compilatie-eenheid) kunnen eenvoudig aangeroepen worden door de functienaam op te geven en de lijst van argumenten. We vestigen hier nogmaals de aandacht op het feit dat het aantal argumenten in de lijst gelijk moet zijn aan het aantal parameters die door de functie geaccepteerd worden.
Syntax:
LocalScriptFunctionCall: FunctionName Arguments FunctionName: Identifier Arguments: ( ) (ArgumentsList) ArgumentsList: Assignexpression ArgumentList, Assignexpression
Functies binnen een zelfde compilatie-eenheid kunnen aangeroepen worden voor ze gedeclareerd zijn, zoals onderstaand voorbeeld duidelijk aantoont.
Voorbeeld:
function test2(param) { return test1(param+1); }; function test1(val) { return val*val; };
Verklaring:
Aan de hand van dit voorbeeld wordt de werking van bovenstaande functies uitgelegd. Stel dat we functie test2 willen uitvoeren en we geven één argument mee, zoals vereist: de variabele param met waarde 2. Deze functie roept de functie test1 aan, en geeft op zijn beurt de variabele 3 aan functie test1 door. Immers, ze verhoogt de variabele die ze zelf ontvangt, met 1. De functie test1 geeft als resultaat 9 (3x3) terug aan de functie test2. Het resultaat van functie test2 is dus 9.
De aanroep van functies moet met de externe functie-aanroep gebeuren wanneer de functie gedeclareerd is in een externe compilatie-eeneheid. Deze functie-aanroep is zeer analoog met de voorgaande. Hier moet echter de functie-aanroep voorafgegaan worden door de naam van de externe compilatie-eenheid.
Syntax:
ExternalScriptFunctionCall: ExternalScriptName # FunctionName Arguments ExternalScriptName: Identifier
Use URL moet gebruikt worden om de externe compilatie-eenheid te specificeren. Het definieert dan ook de mapping tussen de externe eenheid en een naam die kan gebruikt worden binnen de functiedeclaratie. Deze naam en het hekje (#) worden gebruikt om de normale syntax van een functie-aanroep vooraf te gaan.
Voorbeeld:
use url OtherScript http://www.host.com/script Function test3(param) { Return OtherScript#test2(param+1); };
Verklaring:
We willen een script uitvoeren dat zich ergens anders bevindt. Daartoe gaan we eerst een referentie toekennen aan die locatie. Dat gebeurt via het statement use url naam locatie (hier: Otherscript). Als dit is gebeurd, zal telkens wanneer we Otherscript gebruiken, automatisch aan de betreffende locatie worden gerefereerd.
Dat gebeurt dan ook in de functie test3. We geven het argument param mee. Deze variabele wordt met één verhoogd, en dient zo als invoer voor de functie test2 die dus ergens anders staat. Deze laatste wordt geadresseerd door de referentie aan te geven en de specifieke functie die is gevraagd binnen deze referentie (via het kardinaalteken), want er kunnen daar ook meerdere functies staan. De functie test2 voert een bewerking uit met de variabele, en de uitvoer is het resultaat van de functie test3. Wil ik de functie Squeeze gebruiken in de referentie Otherscript, dan wordt de syntax return Otherscript#Squeeze.
Hiervoor wordt een derde aanroepwijze gehanteerd. De lezer vindt meer over deze bibliotheekfuncties in paragraaf 3.5 en 3.6). Een uitgebreide bespreking van een aantal van de standaardbibliotheekfuncties komt ook in hoofdstuk 10 voor.
Syntax:
LibraryFunctionCall: LibraryName . FunctionName Arguments LibraryName: Identifier
Voorbeeld:
Function test4(param) { Return Float.sqrt(Lang.abs(param)+1); };
Verklaring:
Deze functie test4 heeft als argument een variabele. Als uitvoer geeft deze functie de vierkantswortel van de absolute waarde van deze variabele verhoogd met één. Als het meegegeven argument bijvoorbeeld -8 is, dan is het resultaat van de functie test4 gelijk aan de vierkantswortel van de 9.
WMLScript statements bestaan uit expressies en sleutelwoorden met de daarbij horende syntax. Een enkele statement kan meerdere lijnen code betekenen. En omgekeerd kunnen meerdere statements soms op één lijn worden gecodeerd. Ook hier kan opnieuw verwezen worden naar bijvoorbeeld JavaScript, omdat de analogie met WMLScript zeer groot is.
We behandelen de belangrijke statements die praktisch bij een implementatie kunnen gebruikt worden. Meer informatie kan gevonden worden in de bibliografische lijst.
Een empty statement kan gebruikt worden wanneer een statement vereist is, maar geen operatie.
Syntax:
EmptyStatement: ;
Voorbeeld:
While (!poll(device)); // Wacht totdat poll() waar is
Deze worden onder meer gebruikt om waarden toe te wijzen, rekenkundige berekeningen uit te werken en ook om functieaanroepen te maken.
Syntax:
ExpressionStatement: Expression; Expression: AssignmentExpression Expression, AssignExpression
Voorbeelden:
Str = "Hey" + yourName Val3 = prevVal + 4; Counter++; MyValue = counter, myValue2 = val3; Alert("Watch out!"); RetVal = 16*Lang.max(val3, counter)
Een set van statements omsloten door { } is een block statement.
Syntax:
Block: {StatementListopt} StatementList: Statement StatementList Statement
Voorbeeld:
{ var I = 0; var x = Lang.abs(b); popUp(“Remember the times!”); }
Dit statement declareert variabelen met initialisatie.
Syntax:
VariableStatement: var VariableDeclarationList; VariableDeclarationList: VariableDeclaration VariableDeclarationList, VariableDeclaration VariableDeclaration: Identifier VariableInitializeropt VariableInitializer: = ConditionalExpression
Argumenten:
Identifier is de naam van de variabele. ConditionalExpression is de beginwaarde van de variabele die elke toegelaten expressie kan zijn. Deze expressie wordt geëvalueerd telkens wanneer de variable statement wordt uitgevoerd.
Voorbeelden:
function count(str) { var result = 0; // Wordt één keer geïnitialiseerd. while (str !="") { var ind = 0; // Wordt iedere keer geïnitialiseerd. // modify string }; return result }; function example(param) { var a = 0; if (param > a) { var b = a + 1; // a en b kunnen gebruikt worden } else { var c = a + 2; // a, b en c kunnen gebruikt worden }; return a; // a, b en c zijn toegankelijk };
Syntax:
IfStatement: if (Expression) Statement else Statement if (expression) Statement
Voorbeeld:
if (sunShines) { myDay = "Good"; goodDays++; } else myday = "Oh well...";
Deze syntax implementeert een keuze. Als sunShines
waar is,
dan krijgt mijn dag het label goed, en verhoog ik mijn aantal
goede dagen met één. Zoniet geef ik een ander label aan mijn dag.
Syntax:
WhileStatement: while (Expression) Statement
Voorbeeld:
var counter = 0; var total = 0; while (counter < 3) { counter++; total += c; };
Deze syntax is een vertaling van volgende omschrijving:
zolang de waarde van counter (die geïnitialiseerd wordt
op een waarde 0) kleiner is dan drie, verhoog de counter
met één en verhoog het totaal met een waarde c
.
Syntax:
for (Expressionopt; Expressionopt; Expressionopt) Statement for (var VariableDeclarationList; Expressionopt; Expressionopt) Statement
Voorbeeld:
for (var index = 0; index < 100; index++) { Count += index; myFunc(count); };
Dit stukje code doet het volgende: zolang index kleiner is dan 100 (en opnieuw is index geïnitialiseerd op waarde 0) wordt index bij count geteld, en deze count door de functie myFunc verrekend. Daarna wordt de waarde van index met één verhoogd.
Deze statement wordt gebruikt om een huidige while of for loop te beëindigen en verder te gaan met de uitvoering van het programma vanaf het statement volgend op de beëindigde loop. Het is fout wanneer de break statement buiten een while of een for statement wordt gebruikt.
Syntax:
BreakStatement: Break;
Voorbeeld:
function testBreak(x) { var index = 0; while (index < 6) { if (index ==3) break; index++; }; return index*x; };
Dit script vervult volgende taak: zolang de waarde van index kleiner is dan 6, wordt het tussenliggende blok uitgevoerd (in vet weergegeven). Als index gelijk is aan 3 wordt er een break uitgevoerd en wordt de eerstvolgende regel buiten de while-loop uitgevoerd, dus wordt return index*x uitgevoerd. Als index niet gelijk is aan 3 wordt index met één verhoogd. Concreet betekent dit hier dat de while-loop bij de vierde keer onderbroken wordt, en het resultaat van testBreak dus 9 wordt als we als waarde (voor het argument x) 3 meegaven.
Syntax:
ContinueStatement: Continue;
Voorbeeld:
var index = 0; var count = 0; while (index < 5) { index++; if (index == 3) continue; count += index; };
Dit statement wordt gebruikt om de uitvoering van een blok van statements binnen een while of een for lus te beëindigen, en verder te gaan met de uitvoering van de lus met de volgende iteratie. Dit statement zorgt dus niet voor de beëindiging van de lus.
Als we bovenstaand voorbeeld van naderbij bestuderen, dan kunnen we de werking als volgt verklaren.
Eerst worden de variabelen index en count gedeclareerd en krijgen beiden de waarde 0 toegewezen. De while-lus zorgt ervoor dat, zolang index kleiner is dan 5, het in vet gemarkeerde blok van statements uitgevoerd worden. Er wordt hierin nagegaan of de waarde van index gelijk is aan 3. Is dit zo, dan wordt via continue automatisch naar de volgende iteratie overgegaan. Zoniet wordt de waarde count verhoogd met de waarde van index.
Dit statement kan gebruikt worden binnen een functie om de waarde die de functie teruggeeft te specificeren. Is er geen return statement bepaald, of geen enkele van de return statement van de functie uitgevoerd (omdat bijvoorbeeld niet voldoende argumenten werden aangeleverd), wordt standaard een lege string gegenereerd.
Syntax:
return Expressionopt
Voorbeeld:
function square(x) { if (!(Lang.isFloat(x))) return invalid; return x*x; };
De Lang bibliotheek is altijd aanwezig. Volgende standaardbibliotheken zijn tevens beschikbaar:
Bibliotheek | Beschrijving |
---|---|
Float |
Deze bibliotheek bevat een set van typische rekenkundige floating-point functies die vaak door applicaties worden gebruikt. |
String |
Deze bibliotheek bevat functies om met strings te werken. |
URL |
Deze bibliotheek bevat een set van functies om met URL’s om te gaan. |
WMLBrowser |
Deze bibliotheek omvat functies die door WMLScript gebruikt worden om toegang te krijgen tot de bijhorende WML context. |
Dialogs |
Deze bibliotheek bevat een set van typische user interface functies. |
We geven hieronder nog een heel summier overzicht van de beschikbare functies in elk van de bibliotheken. Voor elk van deze functies kan een uitvoerige beschrijving worden gevonden in de WMLScript Library Specification.
WMLScript bevat ook een bibliotheek die niet standaard is en een aantal debugfuncties bevat. Deze functies kunnen gebruikt worden om de scripttoepassingen foutvrij te maken.