Építsen egy tolmácsot Java – ban-hajtsa végre a végrehajtó motort

azok számára, akik most csatlakoztak hozzánk, az elmúlt néhány hónapban a “Java in Depth” oszlopban megvitattam, hogyan lehet egy tolmácsot építeni Java-ban. Az első tolmács oszlopban a tolmács néhány kívánatos tulajdonságát tárgyaltuk; a második oszlopban mind az értelmező, mind az osztálycsomag elrendezését tárgyaltuk a tolmács megvalósításához. Ebben az oszlopban megvizsgáljuk az interpreter futtatását, valamint az ehhez szükséges támogató osztályokat. Végül itt összefoglalom a sorozatot azzal a vitával, hogy egy tolmács hogyan kapcsolható be más Java osztályokba, ezáltal javítva képességeiket.

a vonatkozó bitek áttekintése

hadd kezdjem azzal, hogy felvázolom, mit fedtünk le eddig, és rámutatok a tervezés azon részeire, amelyek fontosabbá válnak, amikor a végrehajtási módot tárgyaljuk. Ezen osztályok részletesebb leírását lásd az előző oszlopokban vagy a forráskód hivatkozásokban, amelyek az alábbi

erőforrások szakaszban találhatók.

.

a tolmács megvalósításában három alaposztály létezik: Program, Statementés Expression. Az alábbiakban bemutatjuk, hogy a három hogyan kapcsolódik egymáshoz:

Program

ez a Program osztály összeragasztja az elemző elemző és végrehajtó összetevőit. Ez az osztály két fő módszert határoz meg, load és run. A load metódus beolvassa az utasításokat egy bemeneti adatfolyamból, és egy utasításgyűjteménybe értelmezi őket, a run metódus iterálja a gyűjteményt, és végrehajtja az egyes utasításokat. A Program osztály a változók gyűjteményét is biztosítja a program számára, valamint egy verem az adatok tárolására.

utasítás

a Statement osztály egyetlen elemzett utasítást tartalmaz. Ez az osztály valójában alosztályozódik egy adott típusú utasításba (PRINT, GOTO, IF stb.), de minden utasítás tartalmazza a execute metódust, amelyet az utasítás végrehajtására hívnak meg egy Program osztálypéldány összefüggésében.

Expression

a Expression osztály egy kifejezés elemzési fáját tartalmazza. A végrehajtás során a value metódust használjuk a kifejezés kiértékelésére és értékének visszaadására. A Statement – hez hasonlóan a Expression osztályt is elsősorban arra tervezték, hogy meghatározott típusú kifejezések alosztályozzák.

ezek az osztályok együttesen alkotják a tolmács alapját. A Program osztály egyidejűleg magába foglalja az elemzési műveletet és a végrehajtási műveletet, míg a Statement és Expression osztályok az általunk megvalósított nyelv tényleges számítási koncepcióit. A tolmácsok építéséről szóló három cikk esetében a példanyelv alapvető volt.

számítástechnikai eszközök

a tolmácsban két végrehajtható osztály található,

Statement

és

Expression

. Először vessünk egy pillantást

Expression

a Expression példányai a expression módszerrel jönnek létre a ParseExpressionosztályban. A ParseExpression osztály az értelmező kifejezést valósítja meg ebben az értelmezőben. Ez az osztály a ParseStatement osztály peer-je, amely a statement metódust használja az alapvető utasítások elemzésére. A Expression példányoknak van egy belső type, amely azonosítja a példány által képviselt operátort, és két módszer, a value és a stringValue, amelyek visszaadják a kifejezés számított értékét. Továbbá, amikor egy Kifejezéspéldány létrejön, névlegesen két paramétert kap, amelyek a kifejezés működésének bal és jobb oldalát képviselik. Forrás formában látható, a kifejezés első része a következő:

class Expression { Expression arg1, arg2; int oper; final static int OP_ADD = 1; // Addition '+' final static int OP_SUB = 2; // Subtraction '-' final static int OP_MUL = 3; // Multiplication '*' final static int OP_DIV = 4; // Division '/' final static int OP_BNOT = 19; // Boolean negation '.NOT.' final static int OP_NEG = 20; // Unary minus

mint a fenti kódban látható, vannak a példányváltozók, az oper nevű operátor típus és a művelet két fele arg1 és arg2, majd néhány konstans a különböző típusok meghatározásához. Ezenkívül két konstruktor van, amelyeket a kifejezés elemző használ; ezek két kifejezésből új kifejezést hoznak létre. Forrásuk az alábbiakban látható:

protected Expression(int op, Expression a, Expression b) throws BASICSyntaxError { arg1 = a; arg2 = b; oper = op; /* * If the operator is a boolean, both arguments must be boolean. */ if (op > OP_GE) { if ( (! (arg1 instanceof BooleanExpression)) || (! (arg2 instanceof BooleanExpression)) ) throw new BASICSyntaxError(typeError); } else { if ((arg1 instanceof BooleanExpression) || (arg2 instanceof BooleanExpression)) throw new BASICSyntaxError(typeError); } } protected Expression(int op, Expression a) throws BASICSyntaxError { arg2 = a; oper = op; if ((oper == OP_BNOT) && (! (arg2 instanceof BooleanExpression))) throw new BASICSyntaxError(typeError); }

az első konstruktor tetszőleges kifejezési objektumot épít, a második pedig egy “unary” kifejezési objektumot-például unary mínusz. Egy dolgot meg kell jegyezni, hogy ha csak egy argumentum van, akkor az arg2 értéket tárolja.

a Expression osztályban leggyakrabban használt módszer a value, amelyet a következőképpen határozunk meg:

 double value(Program pgm) throws BASICRuntimeError { switch (oper) { case OP_ADD : return arg1.value(pgm) + arg2.value(pgm); case OP_SUB : return arg1.value(pgm) - arg2.value(pgm); ... etc for all of the other operator types. ...

láthatja, hogy minden kifejezésobjektum egy operátorból és egy vagy két argumentumból álló tuple-t képvisel. A kifejezésvégrehajtó motor ilyen módon történő megtervezésének szórakoztató része az, hogy amikor ezt a kifejezéssorozatot a Expression objektum alapján állítja össze, akkor a kifejezés értékét egyszerűen a value metódus meghívásával számíthatja ki. A value metódus rekurzív módon meghívja a kifejezést alkotó két argumentum value metódusát, alkalmazza a műveletet rájuk, és visszaadja az eredményt. Ezt a kialakítást úgy használták, hogy a kifejezések könnyen érthetők legyenek.

az osztályszerkezet tisztán tartása érdekében az összes számítási egység-az állandóktól a trigonometrikus függvényekig-a Expression alosztályai. Ez az ötlet, amelyet szégyentelenül loptak el a Lisp-től, teljesen magában foglalja az értékelés “okozásának” fogalmát, az értékelés “hogyan” tényleges megvalósításától kezdve. Annak bemutatásához, hogy ezt az elvet hogyan alkalmazzák, csak a Expressionnéhány speciális alosztályát kell megvizsgálnunk.

a COCOA nevű Basic verzióm Konstansait a ConstantExpression osztály képviseli, amely a Expression alosztályba sorolja, és egyszerűen tárolja a numerikus értéket egy tagértékben. A forráskód ConstantExpression fogalmilag az alábbiakban látható. Azért mondom, hogy “koncepcionálisan”, mert úgy döntöttem, hogy a StringConstantExpression és a NumericConstantExpression egy osztályba sorolom. Tehát a valós osztály tartalmaz egy konstruktort, amely konstansot hoz létre egy string argumentummal, és annak értékét karakterláncként adja vissza. A következő kód megmutatja, hogy a ConstantExpression osztály hogyan kezeli a numerikus állandókat.

class ConstantExpression extends Expression { private double v; ConstantExpression(double a) { super(); v = a; } double value(Program pgm) throws BASICRuntimeError { return v; }}

a fenti kód A Expression bonyolultabb konstruktorait egy példányváltozó egyszerű tárolásával helyettesíti; a value metódust egyszerűen a tárolt érték visszatérésével helyettesítjük.

igaz, hogy kódolhatja a Expression osztályt, hogy elfogadja a konstruktoraiban egy állandót, amely megmentene egy osztályt. A Expression megtervezésének egyik előnye azonban az, hogy a Expression kód maximálisan általános marad. Úgy találom, hogy ez a kódolási stílus segít kiküszöbölni a speciális esetek összetettségét, így amikor “végeztem” a Expression kóddal, továbbléphetek a kifejezések más aspektusaira anélkül, hogy újra és újra megvizsgálnám az alaposztályt. Az előny világosabbá válik, ha belemerülünk a Expression egy másik alosztályába, amelynek neve FunctionExpression.

a FunctionExpression osztályban két tervezési követelmény volt, amelyeket úgy éreztem, hogy teljesíteni kell a tolmács rugalmassága érdekében. Az első a szabványos alapfunkciók megvalósítása volt; a másik az volt, hogy a függvények argumentumainak elemzését ugyanabba az osztályba foglalja, amely ezeket a funkciókat megvalósította. A második követelményt, az elemzést az a vágy motiválta, hogy ezt az alapvető bővíthetőséget további függvénykönyvtárak létrehozásával tegye lehetővé, amelyeket a FunctionExpressionalosztályaként lehet átadni az elemzőnek. Ezenkívül az átadott osztályokat az elemző felhasználhatja a felhasználó programja számára elérhető funkciók számának növelésére.

a FunctionExpression osztály csak mérsékelten bonyolultabb, mint a ConstantExpression, és az alábbiakban tömörített formában jelenik meg:

 1 class FunctionExpression extends Expression { 2 3 double value(Program p) throws BASICRuntimeError { 4 try { 5 switch (oper) { 6 case RND : 7 if (r == null) 8 r = p.getRandom(); 9 return (r.nextDouble() * arg2.value(p));10 case INT :11 return Math.floor(arg2.value(p));12 case SIN :13 return Math.sin(arg2.value(p));14 15 default :16 throw new BASICRuntimeError("Unknown or non-numeric function.");17 }18 } catch (Exception e) {19 if (e instanceof BASICRuntimeError)20 throw (BASICRuntimeError) e;21 else22 throw new BASICRuntimeError("Arithmetic Exception.");23 }24 }

a fenti forrás bemutatja a value módszer megvalósítását. Az oper változót újra felhasználják a függvényazonosság megőrzésére,és az arg1 és arg2 által hivatkozott Kifejezésobjektumokat maguknak a függvényeknek az argumentumaként használják. Végül van egy nagy kapcsolónyilatkozat, amely elküldi a kérést. Az egyik érdekes szempont, hogy a value módszer elkapja a lehetséges aritmetikai kivételeket, és átalakítja őket BASICRuntimeError példányokká. A FunctionExpression elemzési kód az alábbiakban látható, ismét tömörítve a helytakarékosság érdekében. (Ne feledje, hogy az összes forráskód elérhető az erőforrások szakasz linkjeivel.)

 1 static FunctionExpression parse(int ty, LexicalTokenizer lt) throws BASICSyntaxError { 2 FunctionExpression result; 3 Expression a; 4 Expression b; 5 Expression se; 6 Token t; 7 8 t = lt.nextToken(); 9 if (! t.isSymbol('(')) {10 if (ty == RND) {11 lt.unGetToken();12 return new FunctionExpression(ty, new ConstantExpression(1));13 } else if (ty == FRE) {14 lt.unGetToken();15 return new FunctionExpression(ty, new ConstantExpression(0));16 }17 throw new BASICSyntaxError("Missing argument for function.");18 }19 switch (ty) {20 case RND:21 case INT:22 case SIN:23 case COS:24 case TAN:25 case ATN:26 case SQR:27 case ABS:28 case CHR:29 case VAL:30 case STR:31 case SPC:32 case TAB:33 case LOG:34 a = ParseExpression.expression(lt);35 if (a instanceof BooleanExpression) {36 throw new BASICSyntaxError(functions.toUpperCase()+" function cannot accept boolean expression.");37 }38 if ((ty == VAL) && (! a.isString()))39 throw new BASICSyntaxError(functions.toUpperCase()+" requires a string valued argument.");40 result = new FunctionExpression(ty, a);41 break; 42 default:43 throw new BASICSyntaxError("Unknown function on input.");4445 }46 t = lt.nextToken();47 if (! t.isSymbol(')')) {48 throw new BASICSyntaxError("Missing closing parenthesis for function.");49 }50 return result;51 }

vegye figyelembe, hogy ez a kód kihasználja azt a tényt, hogy a ParseStatement kifejezéselemző már rájött, hogy egy kifejezést néz, és átadta a kifejezés azonosságát az as paraméterben ty. Ehhez az elemzőnek csak meg kell találnia a nyitó zárójelet és a záró zárójelet, amelyek tartalmazzák az argumentumokat. De nézd meg alaposan: a #9-től #18-ig terjedő sorokban az elemző lehetővé teszi, hogy egyes függvényeknek ne legyen argumentuma (ebben az esetben RND és FRE). Ez bizonyítja azt a rugalmasságot, amelyet a függvény Alosztályának ebbe az osztályba történő beépítése biztosít, ahelyett, hogy az összes függvényt arra kényszerítené, hogy megfeleljen valamilyen előre meghatározott sablonnak. Adott függvénytípus a paraméterben ty, a switch utasítás kiválaszt egy ágat, amely elemezheti az adott függvényhez szükséges argumentumokat, legyenek azok húrok, számok, egyéb kifejezések stb.

egyéb szempontok: húrok és tömbök

a BASIC nyelv két másik részét a COCOA tolmács valósítja meg: húrok és tömbök. Először nézzük meg a húrok végrehajtását.

a karakterláncok változóként történő megvalósításához a Expression osztályt úgy módosították, hogy tartalmazza a “karakterlánc” kifejezések fogalmát. Ez a módosítás két kiegészítés formájában történt: isString és stringValue. E két új módszer forrása az alábbiakban látható.

 String stringValue(Program pgm) throws BASICRuntimeError { throw new BASICRuntimeError("No String representation for this."); } boolean isString() { return false; }

nyilvánvaló, hogy egy BASIC program számára nem túl hasznos az alapkifejezés karakterlánc-értékének megszerzése (amely mindig numerikus vagy logikai kifejezés). A hasznosság hiányából arra lehet következtetni, hogy ezek a módszerek akkor nem tartoztak a Expression – be, hanem a Expression alosztályába tartoztak. Ha azonban ezt a két módszert az alaposztályba helyezzük, az összes Expression objektum tesztelhető, hogy valóban húrok-e.

egy másik tervezési megközelítés az, hogy a numerikus értékeket karakterláncként adja vissza egy StringBuffer objektum segítségével érték létrehozásához. Így például ugyanazt a kódot lehet átírni, mint:

 String stringValue(Program pgm) throws BASICRuntimeError { StringBuffer sb = new StringBuffer(); sb.append(this.value(pgm)); return sb.toString(); }

Ha pedig a fenti kódot használjuk, akkor kizárhatjuk a isString használatát, mert minden kifejezés karakterlánc értéket adhat vissza. Ezenkívül módosíthatja a value metódust, hogy megpróbáljon visszaadni egy számot, ha a kifejezés egy karakterláncra értékel, a valueOf java.lang.Doublemetódusán keresztül futtatva. Sok nyelven, mint például a Perl, TCL és REXX, ez a fajta amorf gépelés használják nagy előnye. Mindkét megközelítés érvényes, és a tolmács tervezése alapján kell választania. A Basicben a tolmácsnak hibát kell visszaadnia, amikor egy karakterláncot rendelnek egy numerikus változóhoz, ezért az első megközelítést választottam (hiba visszaadása).

ami a tömböket illeti, különböző módon tervezheti meg a nyelvét, hogy értelmezze őket. C a tömbelemek körüli szögletes zárójeleket használja, hogy megkülönböztesse a tömb indexhivatkozásait azoktól a függvényhivatkozásoktól, amelyek zárójelekkel rendelkeznek az argumentumaik körül. A basic nyelvtervezői azonban úgy döntöttek, hogy zárójeleket használnak mind a függvényekhez, mind a tömbökhöz, így amikor a NAME(V1, V2) szöveget látja az elemző, ez lehet függvényhívás vagy tömbhivatkozás.

a lexikális elemző különbséget tesz a zárójelben szereplő tokenek között, először feltételezve, hogy függvények, és teszteli azokat. Ezután megnézi, hogy kulcsszavak vagy változók-e. Ez a döntés megakadályozza, hogy a program meghatározza a “SIN” nevű változót.”Minden olyan változót, amelynek neve egy függvénynévnek felel meg, a lexikai elemző függvény tokenként adja vissza. A második trükk, amelyet a lexikai elemző használ, annak ellenőrzése, hogy a változó nevét azonnal követi-e `(‘. Ha igen, akkor az analizátor feltételezi, hogy tömbhivatkozás. Ha ezt elemezzük a lexikális analizátorban, akkor a `MYARRAY ( 2 )‘ karakterláncot nem értelmezzük érvényes tömbként (jegyezzük meg a változó neve és a nyitott zárójel közötti helyet).

a tömbök megvalósításának utolsó trükkje a Variable osztály. Ezt az osztályt egy változó példányához használjuk, és amint azt a múlt havi oszlopban tárgyaltam, ez egy Tokenalosztály. Ugyanakkor van néhány gépe is a tömbök támogatására, és ezt mutatom be alább:

class Variable extends Token { // Legal variable sub types final static int NUMBER = 0; final static int STRING = 1; final static int NUMBER_ARRAY = 2; final static int STRING_ARRAY = 4; String name; int subType; /* * If the variable is in the symbol table these values are * initialized. */ int ndx; // array indices. int mult; // array multipliers double nArrayValues; String sArrayValues;

a fenti kód a változóhoz társított példányváltozókat mutatja, mint a ConstantExpression osztályban. Az egyik, hogy a választás az osztályok számát kell használni, szemben a komplexitás egy osztály. Az egyik tervezési lehetőség lehet egy Variable osztály felépítése, amely csak skaláris változókat tartalmaz, majd hozzáad egy ArrayVariable alosztályt a tömbök bonyodalmainak kezeléséhez. Úgy döntöttem, hogy összekapcsolom őket, a skaláris változókat lényegében 1 hosszúságú tömbökké alakítva.

ha elolvassa a fenti kódot, tömbindexeket és szorzókat fog látni. Ezek azért vannak itt, mert a BASIC többdimenziós tömbjeit egyetlen lineáris Java tömb segítségével valósítják meg. A lineáris index a Java tömbbe manuálisan kerül kiszámításra a multiplikátor tömb elemeinek felhasználásával. Az alapprogramban használt indexek érvényességét úgy ellenőrizzük, hogy összehasonlítjuk őket az indexek ndx tömbjének maximális jogi indexével.

például egy 10, 10 és 8 dimenziójú ALAPTÖMB esetében a 10, 10 és 8 értékek az ndx-ben vannak tárolva. Ez lehetővé teszi az expresszióértékelő számára, hogy teszteljen egy “index határon kívüli” feltételt az ALAPPROGRAMBAN használt szám összehasonlításával az ndx-ben tárolt maximális jogi számmal. A példánkban szereplő szorzó tömb az 1, 10 és 100 értékeket tartalmazza. Ezek az állandók azokat a számokat képviselik, amelyeket egy többdimenziós tömbindex specifikációból lineáris tömbindex specifikációvá történő leképezéshez használnak. A tényleges egyenlet:

Java Index = Index1 + Index2 * az Index1 + Index3 maximális mérete * (az Index1 * MaxSizeIndex 2 maximális mérete)

a Variable osztály következő Java tömbje az alábbiakban látható.

 Expression expns;

az expns tömb a “A(10*B, i) néven írt tömbök kezelésére szolgál.”Ebben az esetben az indexek valójában kifejezések, nem pedig állandók, ezért a hivatkozásnak mutatókat kell tartalmaznia azokra a kifejezésekre, amelyeket futás közben értékelnek. Végül van ez a meglehetősen csúnya kinézetű kóddarab, amely kiszámítja az indexet attól függően, hogy mit adtak át a programban. Ez a privát módszer az alábbiakban látható.

 private int computeIndex(int ii) throws BASICRuntimeError { int offset = 0; if ((ndx == null) || (ii.length != ndx.length)) throw new BASICRuntimeError("Wrong number of indices."); for (int i = 0; i < ndx.length; i++) { if ((ii < 1) || (ii > ndx)) throw new BASICRuntimeError("Index out of range."); offset = offset + (ii-1) * mult; } return offset; }

a fenti kódot tekintve megjegyezzük, hogy a kód először ellenőrzi, hogy a tömb hivatkozásakor a megfelelő számú indexet használták-e, majd hogy minden index az adott index törvényes tartományán belül volt. Ha hibát észlel, kivételt dob a tolmács. A numValue és stringValue metódusok a változó értékét számként vagy karakterláncként adják vissza. Ez a két módszer az alábbiakban látható.

 double numValue(int ii) throws BASICRuntimeError { return nArrayValues; } String stringValue(int ii) throws BASICRuntimeError { if (subType == NUMBER_ARRAY) return ""+nArrayValues; return sArrayValues; }

vannak további módszerek a változó értékének beállítására, amelyek itt nem jelennek meg.

az egyes darabok megvalósításának összetettségének nagy részét elrejtve, amikor végre eljön az ideje az alapprogram végrehajtásának, a Java kód meglehetősen egyszerű.

a kód futtatása

az alapvető utasítások értelmezésére és végrehajtására szolgáló kódot a

run

módszer

Program

osztály. Ennek a módszernek a kódja az alábbiakban látható, és átmegyek rajta, hogy rámutatjak az érdekes részekre.

 1 public void run(InputStream in, OutputStream out) throws BASICRuntimeError { 2 PrintStream pout; 3 Enumeration e = stmts.elements(); 4 stmtStack = new Stack(); // assume no stacked statements ... 5 dataStore = new Vector(); // ... and no data to be read. 6 dataPtr = 0; 7 Statement s; 8 9 vars = new RedBlackTree();1011 // if the program isn't yet valid.12 if (! e.hasMoreElements())13 return;1415 if (out instanceof PrintStream) {16 pout = (PrintStream) out;17 } else {18 pout = new PrintStream(out);19 }

a fenti kód azt mutatja, hogy a run módszer egy InputStream és egy OutputStream – et használ a végrehajtó program “konzoljaként”. A 3. sorban az e felsorolási objektum az stmts nevű gyűjtemény utasításkészletére van állítva. Ehhez a gyűjteményhez egy bináris keresési fa variációját használtam, amelyet “vörös-fekete” fának hívtak. (A bináris keresési fákkal kapcsolatos további információkért lásd az előző oszlopomat az Általános gyűjtemények felépítéséről.) Ezt követően két további gyűjtemény jön létre-az egyik a Stack, a másik pedig a Vectorhasználatával. A verem ugyanúgy használható, mint a verem bármely számítógépen, de a vektort kifejezetten az alapprogram adatnyilatkozataihoz használják. A végső gyűjtemény egy másik vörös-fekete fa, amely az alapprogram által meghatározott változók referenciáit tartalmazza. Ez a fa az a szimbólumtábla, amelyet a program futása közben használ.

az inicializálás után a bemeneti és kimeneti adatfolyamok be vannak állítva, és ha e Nem null, akkor a deklarált adatok gyűjtésével kezdjük. Ez a következő kód szerint történik.

 /* First we load all of the data statements */ while (e.hasMoreElements()) { s = (Statement) e.nextElement(); if (s.keyword == Statement.DATA) { s.execute(this, in, pout); } }

a fenti ciklus egyszerűen megvizsgálja az összes utasítást, és minden talált ADATUTASÍTÁST végrehajtanak. Az egyes ADATUTASÍTÁSOK végrehajtása beszúrja az adott utasítás által deklarált értékeket az adattár vektorába. Ezután végrehajtjuk a megfelelő programot, amelyet a következő kóddarab segítségével hajtunk végre:

 e = stmts.elements(); s = (Statement) e.nextElement(); do { int yyy; /* While running we skip Data statements. */ try { yyy = in.available(); } catch (IOException ez) { yyy = 0; } if (yyy != 0) { pout.println("Stopped at :"+s); push(s); break; } if (s.keyword != Statement.DATA) { if (traceState) { s.trace(this, (traceFile != null) ? traceFile : pout); } s = s.execute(this, in, pout); } else s = nextStatement(s); } while (s != null); }

amint az a fenti kódból látható, az első lépés az e. a következő lépés az első utasítás beolvasása az s változóba, majd a végrehajtási ciklus beírása. Van néhány kód, amely ellenőrzi a bemeneti adatfolyam függőben lévő bemenetét, hogy lehetővé tegye a program előrehaladásának megszakítását a program beírásával, majd a hurok ellenőrzi, hogy a végrehajtandó utasítás ADATNYILATKOZAT lenne-e. Ha igen, akkor a hurok kihagyja az utasítást, ahogy már végrehajtották. Az összes adatutasítás végrehajtásának meglehetősen bonyolult technikájára azért van szükség, mert a BASIC lehetővé teszi, hogy a READ utasításnak megfelelő ADATUTASÍTÁSOK bárhol megjelenjenek a forráskódban. Végül, ha a nyomkövetés engedélyezve van, a rendszer kinyomtat egy nyomkövetési rekordot, és meghívja a s = s.execute(this, in, pout); nagyon nem nyomó utasítást. A szépség az, hogy az alapfogalmak könnyen érthető osztályokba történő beágyazásának minden erőfeszítése triviálissá teszi a végső kódot. Ha ez nem triviális, akkor talán van egy nyom, hogy lehet, hogy egy másik módja annak, hogy szét a design.

becsomagolás és további gondolatok

a tolmácsot úgy tervezték, hogy szálként futhasson, így egyszerre több COCOA tolmács szál is futhat a programterében. Továbbá a funkcióbővítés használatával olyan eszközt tudunk biztosítani, amellyel ezek a szálak kölcsönhatásba léphetnek egymással. Volt EGY program az Apple II-hez, majd később a PC-hez és a Unix-hoz, C-robots néven, amely interakciós” robot ” entitások rendszere volt, amelyeket egy egyszerű alapvető származékos nyelv segítségével programoztak be. A játék sok órányi szórakozást nyújtott nekem és másoknak, de kiváló módja volt a számítás alapelveinek bemutatására a fiatalabb diákok számára (akik tévesen azt hitték, hogy csak játszanak, és nem tanulnak). A Java alapú tolmács alrendszerek sokkal erősebbek, mint a Java előtti társaik, mert azonnal elérhetők bármely Java platformon. COCOA futott Unix rendszerek és Macintoshes ugyanazon a napon kaptam dolgozik egy Windows 95 alapú PC. Míg a Java – t a szál vagy az ablak eszközkészlet implementációinak inkompatibilitása veri fel, ezt gyakran figyelmen kívül hagyják: sok kód “csak működik.”

Chuck McManis jelenleg a Freegate Corp. rendszerszoftverének igazgatója, amely egy vállalkozás által finanszírozott induló vállalkozás, amely az internetes piac lehetőségeit vizsgálja. Mielőtt csatlakozott a FreeGate-hez, Chuck a Java csoport tagja volt. Csatlakozott a Java csoporthoz közvetlenül a FirstPerson Inc. megalakulása után. a portable OS csoport tagja volt (a Java operációs rendszerért felelős csoport). Később, amikor a FirstPerson feloszlott, ő maradta csoporttal a Java platform alpha and betaversions fejlesztésén keresztül. Ő hozta létre az első” All Java ” honlapot az interneten, amikor 1995 májusában elvégezte a Sun javaversion kezdőlapjának programozását. Emellett kifejlesztette az acryptographic library-t a Java-hoz és a Java classloader verzióit, amelyek digitális aláírások alapján képesek szűrni az osztályokat.Mielőtt csatlakozott a Firstpersonhez, Chuck az operációs rendszerekben dolgozotta SunSoft területe, hálózati alkalmazások fejlesztése, ahol tettea NIS + kezdeti tervezése. Is, nézd meg a kezdőlapot. : END_BIO

Tudjon meg többet erről a témáról

  • itt találhatók a fent hivatkozott forrásfájlokra mutató linkek:
    • ConstantExpression.java
    • FunctionExpression.java
    • Program.java
    • utasítás.java
    • StringExpression.java
    • változó.java
    • VariableExpression.java
  • és itt van egy .A forrásfájlok ZIP fájlja:
    mélység.zip
  • “Uncommon Lisp” – Java nyelven írt Lisp tolmács
    http://user03.blue.aol.com/thingtone/workshop/lisp.htm
  • Mike Cowlishaw Java nyelven írt NetREXX tolmácsa
    http://www2.hursley.ibm.com/netrexx/
  • a USENET BASIC GYIK egy régi példánya (még mindig hasznos információkkal rendelkezik benne.)
    http://whitworth.me.ic.ac.uk/people/students/djbur/qbasic.htm
  • kakaó, Java-ban írt alapvető tolmács
    http://www.mcmanis.com/~cmcmanis/java/javaworld/examples/BASIC.html
  • Chuck Java források oldala
    http://www.mcmanis.com/~cmcmanis/java/javaworld/
  • Tcl tolmács Java nyelven
    http://www.cs.cornell.edu/home/ioi/Jacl/
  • :
  • “Hogyan építsünk tolmácsot Java – ban, 2.résza szerkezet”
    a trükk az alaposztályok összeállításához egy egyszerű tolmács számára.
  • “Hogyan építsünk egy tolmácsot a Java-ban, 1.részaz alapok”
    a szkriptnyelvet igénylő összetett alkalmazásokhoz a Java használható a tolmács megvalósítására, szkriptkészítési képességek hozzáadásával bármely Java alkalmazáshoz.
  • “lexikális elemzés, 2.Részalkalmazás létrehozása”
    a StreamTokenizer objektum használata interaktív számológép megvalósításához.
  • ” Lexical analysis and JavaPart 1″
    Ismerje meg, hogyan konvertálhat ember által olvasható szöveget géppel olvasható adatokká a StringTokenizer és StreamTokenizer osztályok segítségével.
  • “Kód újrafelhasználás és objektum-orientált rendszerek”
    segítő osztályt használ a dinamikus viselkedés kikényszerítésére.
  • ” konténer támogatás objektumok Java 1.0.2″
    szervező objektumok egyszerű, ha őket konténerekbe. Ez a cikk végigvezeti Önt egy konténer tervezésén és megvalósításán.
  • ” a Java class loaders alapjai”
    a Java architektúra ezen kulcsfontosságú összetevőjének alapjai.
  • ” nem használja a szemétgyűjtést”
    minimalizálja a kupacverést a Java programokban.
  • “Threads and applet and visual controls”
    a sorozat utolsó része több adatcsatorna olvasását vizsgálja.
  • “kommunikációs csatornák használata kisalkalmazásokban, 3.rész”
    Visual Basic stílusú technikák fejlesztése az kisalkalmazások tervezéséhez-és a hőmérsékletek konvertálása a folyamat során.
  • ” Synchronizing threads in Java, Part II”
    Ismerje meg, hogyan írhat adatcsatorna osztályt, majd hozzon létre egy egyszerű példaalkalmazást, amely szemlélteti az osztály valós megvalósítását.
  • ” Synchronizing threads in Java”
    Chuck McManis, a Java csapat korábbi fejlesztője végigvezeti Önt egy egyszerű példán, amely bemutatja, hogyan kell szinkronizálni a szálakat a megbízható és kiszámítható applet viselkedés biztosítása érdekében.

Vélemény, hozzászólás?

Az e-mail-címet nem tesszük közzé.