Típusszerkezet
Az Aikido egy gyengén típusos nyelv, és mivel interpretált, ezért minden objektum típusa futásidőben dől el. Az Aikido csak dinamikus típusokat tartalmaz.
Elemi típusok
Az Aikido számos, más nyelvekből ismert elemi típuson kívül, sok más konstrukciót is típusként kezel. Előbbiekről lesz szó az "Alaptípusok", utóbbiakról a "Speciális típusok" alfejezetben.
Alaptípusok
Aikidoban az alaptípusok a C++-ban, és Java-ban is megtalálható típusok:
- Integer: 64 bites egész számok kb. -9e18-től 9e18-ig. Túlcsordulásvizsgálat nem történik.
- Byte: 8 bites egész számok a 0-255 tartományból.
- Character:
Az Aikido az ASCII 256 karakteres szabványát használja karakterek tárolására, így például a magyar ékezetes betűket sem tudja kezelni.
A karakterek egyben egész számokat is jelölnek, a 0-255-ös tartományból.
- Real:
IEEE szabvány szerinti, dupla pontosságú valós (valójában persze racionális) számok.
Megközelítőleg a 2.2e-308 to 1.79e+308-es intervallumot öleli fel, bizonyos pontatlansággal.
A biteltoló, és a bitenkénti operátorok kivételével minden, az Integer-eknél használatos operátor használható.
Speciális típusok
A speciális típusok, amelyek nem feltétlenül találhatóak meg az Aikido mintájául szolgáló nyelvek mindegyikében:
- Object:
Az object a felhasználók által (a class vagy monitor kulcsszavakkal definiált típusokat jelöli.
Egy ilyen típusú elem adattagjait a . operátorral érhetjük el.
Az Object típusú elemeket a new operátorral hozhatjuk létre, és vagy a garbage collector,
vagy a delete operátor használata pusztítja el. A null objektum a speciális null objektumot definiálja.
- Stream:
A Stream-ek lényegében bizonyos I/O portokhoz kötött csatornák, amelyeket adatok küldésére, illetve fogadására lehet használni. A Stream a következő csatlakozhat fájlokhoz, a perifériákhoz illetve a hálózathoz.
Egy Stream akkor jön létre, amikor a hozzá kötött fájlt megnyitják, vagy amikor a hálózati kapcsolat létrejön. Stream-ekből való olvasásra, és beléjük történő írásra a -> operátor használatos.
A Stream-ek használatára külön könyvtár használható Aikido-ban. Az alapértelmezés szerinti stream-ekhez nem kell könyvtárakat használni (stdin, stdout, stderr).
- Function:
A függvénytípus szintaxisa, és működése teljesen hasonló a más programnyelvek (C++, Java) függvényeihez. Különlegesség, hogy függvény bárhol definiálható a programtörzsön belül.
- Thread:
A szálak speciális függvénytípusú objektumok. Működésük és használatuk a Java száltípusához hasonlóak.
- Class:
Az osztályok a felhasználók által definiált saját típusok. Az osztályok a legtöbb programnyelvhez hasonlóan adattagokat, és metódusokat tartalmaznak.
- Monitor:
A monitorok olyan, a felhasználók által definiált saját típusok, amelyek adattagjaihoz és metódusaihoz kizárólagos hozzáférést biztosít az egyes folyamatoknak. Ennek a jelentősége a többszálú programok készítésénél jelentkezik.
- Package:
A package-ek lényegében összefüggő programrészek. Funkciójuk hasonló a Java-ban látott package fogalomhoz. A következő két kódrészlet egymással ekvivalens csomag struktúrát hoz létre:
//Ez a definíció ugyanazt hozza létre...
package javax.swing {
//törzs
}
//... mint ez
package javax {
public package swing {
//törzs
}
}
Az Aikido egy interpretált nyelv, így a package-ek használata néhány veszélyt rejt magában. Tekintsük a következő példakódot:
package Parser { // Parser csomag
function getToken() {
// törzs
}
// egyéb metódusok, adattagok
}
function print (s) { // egy, a csomagon kívüli függvény
// do something
}
package Parser { // A Parser csomag további bővítése (ez esetleg más fájlban is elhelyezkedhet)
function error (s) { // valamilyen hibakezelésre szolgáló függvény
print (“Error: + s) // eredménye: “Cannot call a value of type none”
}
}
A fenti példaprogram futtatása esetén hibát kapunk, mégpedig pontosan akkor, amikor az error függvényben használt print()-et szeretnénk használni.
Ennek oka, hogy interpretált nyelveknél a kód leírásának sorrendje is nagyon fontos, csomagok esetében az Aikido a csomag összes bővítését a csomag legelső definíciójához fűzi. Emiatt az error() függvény akkor hívódik meg, amikor a print() függvény még nem is lett definiálva.
- Interface:
Az interfészek lényegében szerződések, csak függvények specifikációját tartalmazza. Hozzáférési szintet nem lehet adni az interfészek tagfüggvényeinek, csak az implementációkban adható meg ez az információ.
Az interfészek tulajdonságai teljesen a Java-hoz hasonlóak.
- Pointer:
A memória típusú érték esetén a pointer egy, a blokk egy címére mutató változó. A pointerek esetében használható.
- Memory:
Egy memória típusú érték a memória egy blokkját reprezentálja. Egy ilyen blokk létrehozása a System.malloc(n) függvényhívással történik. Az Aikido az alapértelmezett szemétgyűjtési szabályok szerint kezeli a memóriablokkokat.
Az Aikidoban a memóriaértékeket egy, a memóriablokkot bejáró pointerrel tudjuk kezelni. A pointer csak a létrehozásnál megadott blokkot járhatja be. Ha a pointer műveleteivel (+, -) kiszaladnánk a megadott blokkból, az Aikido arra egy hibaüzenettel válaszol, és a hibás értékkel már nem tér vissza.
- None:
Ez a speciális üres típus, aminek típusértékhalmaza az üres halmaz, így az ilyen típusú változónak értéke sincs. A definiált, kezdőérték nélküli változóknak ez a típusa. Aikidoban tehát ez a típus lényegében minden más típusnak része, azaz minden típus a saját, és a None típus uniója.
Az általános típus
Aikidoban lehetőség van általános típusú változók definiálására. Az ilyen változók dinamikus típusa futás közben változhat.
Használata:
...
generic x;
x=5; //x most Integer
x="alma"; //x most String
...
Típuskonstrukciók
Az Aikido az elemi típusokon felül különböző típuskonstrukciós rendszereket is kínál.
Sorozat konstrukció
A sorozat konstrukció Aikidoban a következő módon került megvalósításra:
Direkt szorzat konstrukció
Aikidoban beépített rekord típus nincs, a direkt szorzat konstrukciót a class kulcsszóval tudjuk létrehozni, mint saját típust.
class szemely(integer id, nev, suly) {
...
}
Vegyes konstrukciók
Típuskonverziók
Az Aikido legfőbb alapelve a típuskonverziók esetében, hogy ami konvertálható, azt konvertálja is.
var nev = "korte";
var darab = 5;
var szoveg = "A " + nev + " gyumolcsbol " + darab + " darab van keszleten.";
szoveg -> stdout; //A körte gyümölcsből 5 darab van keszleten.
Kifejezések konvertálása esetén természetesen adott egy természetes konverziós irány. El kell tudni dönteni a kifejezés kiértékelése előtt, hogy az adott operandus és operátor felállásban milyen típusúként kezeljük a kapott operandusokat.
Az alaptípusok esetében ez a következő szabályokat jelenti:
integer integer |
nem kell konverzió |
integer real |
az integer érték először real-lé konvertálódik, majd megtörténik az operátor kiértékelése |
integer string |
az integer string-gé konvertálódik, majd megtörténik az operátor kiértékelése |
real real |
nem kell konverzió |
string string |
nem kell konverzió |
string integer |
az integer string-gé konvertálódik, majd megtörténik az operátor kiértékelése |
string real |
|
Kifejezések, operátorok
Aikidoban a kifejezések operátorok és operandusok meghatározott szintaxisú sorozata. Aikidoban az operátorok nagyon sokoldalúak, köszönhetően az alapértelmezés szerint meglévő túlterheléseknek.
A következő táblázat tartalmazza az operátorok precedenciáját Aikidoban, felülről lefelé a csökkenő prioritás.
new, operator |
[], (), ., ++ (postfix), -- (postfix) |
sizeof, typeof, cast, !, -, +, ~, ++, -- |
*, /, % |
<< (bit-eltolás balra), >> (aritmetikai bit-eltolás jobbra), >>> (logikai bit-eltolás jobbra) |
<, >, <=, >=, instanceof, in |
==, != |
& (bitenkénti ÉS) |
^ |
| (bitenkénti VAGY) |
&& |
|| |
?: |
-> |
=, +=, -=, *=, /=, %=, <<=, >>=, >>>=, &=, |=, ^= |
A >> és a >>> operátorok közötti különbség az előjelek kezelésében van. A >> operátor előjel kiegészítést is végez balról, míg a >>> operátor előjeltől függetlenül 0-val tölti ki a rendelkezésre álló helyet.
Operátortúlterhelés
Aikidoban lehetőség van bizonyos operátorok túlterhelésére. Ezek a következők:
* |
() |
-> |
[] |
+ |
- |
/ |
% |
~ |
^ |
! |
& |
| |
<< |
>> |
>>> |
< |
> |
<= |
>= |
== |
!= |
sizeof |
typeof |
foreach |
cast |
in |
Az operátorok túlterhelése egész egyszerűen az operátor megvalósítását jelenti az adott osztályban.
Példa:
class Teszt {
public operator + (arg1) {
...
}
}
var x = new Teszt()
x+1 -> stdout
A fenti példakódban az automatikus konverziók is lefutnak, amennyiben azt az x változó típusa szükségessé, és lehetővé teszi.
Az
x+1 operációban az
arg1 paraméter értéke 1, vagyis a kifejezés ugyanazt jelenti mint:
x.operator+(1) .
Operátorok sokoldalúsága
Az Aikido operátorai típustól függően több alapértelmezett jelentéssel is bírhatnank. Ezek közül pár példa:
- vector & vector: Két vektor elemeinek metszete. Eredmény típusa: vector
- vector | vector: Két vektor elemeinek uniója. Eredmény típusa: vektor
- string << integer: A string eltolása balra az adott integer számmal. Eredmény típusa: string
- string >> integer: A string eltolása jobbra az adott integer számmal. Eredmény típusa: string
- vector << integer: A vector eltolása balra az adott integer számmal. Eredmény típusa: vector
- vector >> integer: A vector eltolása jobbra az adott integer számmal. Eredmény típusa: vector
- block < block: A baloldali blokk alblokkja-e a jobboldalinak?
- vector < vector: A baloldali vektorban kevesebb elem van-e mint a jobboldaliban? (map-re ugyanezt jelenti)
- object == object: A két object ugyanazon a memóriacímen található-e?
- class < class: A baloldali osztály leszármazottja-e a jobboldalinak?