Az Anvil egy szerver oldali alkalmazás, amely a Java nyelvre épülő szkript nyelvből és egy template nyelvből áll. Ezenkívül webszerver és néhány egyéb integrált szolgáltatás is megtalálható benne. Szóval az Anvil igazából két nyelvet tömörít magába.
Fontos, hogy az Anvil szkript nyelv java forrásra fordítódik, majd onnan java bájtkódra fordul automatikusan. Ennek az az előnye pl. a PHP-vel szemben, hogy így az Anvil nem zár be a szkript nyelvek világába, hanem az alatta levő Javat is használhatod. (Pl.: JDBC)
Az Anvilnél nem az a lényeg hogy egy kidolgozott mesterséges nyelvet fejlesszenek, ami univerzális. Hanem amire egy webes alkalmazásban szükség van.
Ha gond adódna a megvalósításban akkor meg ott a Java. De az esetek többségében ez nem szükséges, de azért jó tudni, hogy adva van a lehetőség.
Pl. nyilván van benne ciklus, értékadás, stb. mert ez minden nyelvben van. És emellett olyan változó típusokat használ, amelyekre szükség lehet egy webes felületen. Pl. listákat nagyon könnyű vele kezelni.
És gyengén típusos (vagy típus nélküli) szkript nyelv, így gyakorlatilag nem kell kivételeket sem kezelni, mert egy Anvil template az esetek többségében mindig lefut.
Mert az értékadásokat valahogy mindig fogja értelmezni. Így aztán nem kell a különleges helyzetekkel foglalkozni: pl. üres sztring, mi van ha null pointer. Meg ilyesmik.
Persze, nem mindig helyes így, de a gyakorlatban - amikor az ember webre fejleszt - ezek nagyon kényelmes tulajdonságok.
Szóval az Anvil nem mint nyelv szép, hanem azért gyors vele fejleszteni, mert direkt arra fejlesztik ezt a nyelvet, hogy könnyen, gyorsan lehessen vele fejleszteni...
Ha egy utasítás kell és hiányzik, akkor másnapra meg lehet azt írni. Így fejlődött az Anvil. A programozóinak a 10 éves tapasztalatával a szerver oldali alkalmazások fejlesztésében.
Másik és talán legfontosabb tulajdonsága, hogy az Anvil nyelvei modulokból épülnek fel. Ez nagy fokú átláthatóságot tesz lehetővé, amelyre az Anvil esetében nagyon törekedtek. A másik amiért ez nagyon jól jön az az, hogy sokkal Takarékosabb a modulok újrahasznosításával.
Az Anvil a C tipusú nyelvcsaládba tartozik. Befolyással volt rá még a Java, a Python és egy kicsit a Perl is. Van benne runtime typing és static binding a hatásfok növelése érdekében. Megpróbál minden szkriptet modulokba zárni, amelyek így meghívhatók más szkriptekből. A nyelvtan felépítése nem nevezhető jól formáltnak, de megpróbál jól olvasható, félreérthetetlen és következetes lenni.
A Tulajdonságai:
<if expr="myCondition"> <font color="blue"> </if> content here <if expr="myCondition"> </font> </if>
<if expr="myCondition"> <font color="blue">content here</font> <else> content here </if>
<outer expr="myCondition"> <font color="blue"> <inner> content here </inner> </font> </outer>
<outer expr="condition"> <!--header content--> <inner> <!--inner content--> </inner> <!--footer content--> </outer>
A template nyelv nagyon egyszerű. Csak pár utasítás található benne. Ha esetleg kíváncsi vagy a template nyelv összes utasításának BNF leírására, akkor klikk ide.
module { function service(ctx) { println <html><body><pre><ul type=i>; MAX = 100; # simple foreach over range sum = 0; foreach(N; 0..MAX+1) sum += N; println <li>, sum; # simple for for(sum,N=0,0; N<=MAX; N++) sum += N; println <li>,sum; # simple while sum, N = 0, 0; while(N<=MAX) sum += N++; println <li>, sum; # while statement modifier sum, N = 0, 0; sum += N++ while N<=MAX; println <li>, sum; # foreach applier expression N = 0; sum = 0..MAX+1 foreach {|e| N += e; }; println <li>, sum; # reduction println <li>, reduce({|a,b| a+b; }, 2, 0, 0..MAX+1); # piped enumeration purged with foreach sum = 0; foreach( 0..MAX+1 -> {|N| sum += N; } ) ; println <li>, sum; # piped enumeration purged sum = 0; sum = (0..MAX+1 -> {|N| sum += N; }).purge(); println <li>, sum; # eh, using lazy expression evaluation N = 0; sum = ^( N++ + ((N<=MAX)?sum:0) ); println <li>, sum; println </ul><body></html>; } }
A template nyelv címkéi BNF-ben leírva:
dotted-name := symbol ( "." symbol ) * list-of-dotted-names := dotted-name ( "," dotted-name )* import-name := dotted-name [ "." "*" ] import-list := "*" import-list := import-name ( "," import-name )* list-of-assignable-expr := assignable-expr ( "," assignable-expr )* <module [ name="symbolname" ] [ preserve | compress | pack | silent ] > ( <import> | <const> | <var> | <function> | <class> | <namespace> ) * </module> <import ( href="path" | module="symbolmodule" | from="dotted-name" ) ( as="symbolnew-name" | entities="import-list" ) [ taglib="path-to-taglib-xml" ns="symbolnamespace" ] > <namespace name="symbolname" [ preserve | compress | pack | silent ] > ( <import> | <const> | <var> | <function> | <class> | <namespace> ) * </namespace> <class name="symbolname" [ extends="dotted-nameclass" ] [ implements="list-of-dotted-namesinterfaces" ] [ preserve | compress | pack | silent ] > ( <import> | <const> | <var> | <function> </class> <function name="symbolname" ( ( param="symbolparam-name" [ default="exprconst" ] )* [ rest="symbolcollector" ] | params="arguments" ) [ preserve | compress | pack | silent ] > ( <import> | statement ) * </function> <var [static] name="symbolname" [ value="exprinitial-value" ] > <const name="symbolname" value="exprinitial-value" > <print value="exprprintable" ( quote | meta | text | nowrap | nl2br | compress | caps | capsfirst | encode ) | decode ) | uppercase ) | lowercase ) | trim ) * > <replace ...as above... > cdata </replace> <if (expr|true|false)="exprcondition" > statement * [ <else> statement * ] </if> <if (expr|true|false)="exprcondition-1" > statement * <elseif expr="exprcondition-2" > statement * ... <elseif (expr|true|false)="exprcondition-N" > statement * [ <else> statement * ] </if> <while [ label="symbollabel" ] (expr|true|false)="exprcondition" > statement * </while> <return [ value="exprreturn-value" ] > <break [ to="symbollabel" ] > <continue [ to="symbollabel" ] > <switch (expr|by)="exprcandidate" > ( <case value="exprvalue" > statement * | <default> statement * )* </switch> <foreach [ label="symbollabel" ] [ index="list-of-assignable-exprindex" ] [ key="list-of-assignable-exprkey" ] [ value="list-of-assignable-exprvalue" ] (expr|in)="expriterable" > statement * </foreach> <for [ label="symbollabel" ] expr="forexprs" > statement * </for> <eval expr="expr" > <eval<-- statements * //--></eval> <invoke [ params="expr-listparameters" | ( param="exprparam" ) * ] method="symbolmethod" from="exprself" [ super ] > <call [ params="expr-listparameters" | ( param="exprparam" ) * ] function="dotted-namefunction" > <preserve> <compress> <pack> <silent>