ZeptoN正在将程序放入Java
1.簡(jiǎn)介
Java編程語言或“ Java”于1995年引入。然而,在近25年的時(shí)間里,它增加了最初不是核心語言所具有的功能。 此類功能包括枚舉,泛型,對(duì)基本C樣式功能開關(guān)語句的許多增強(qiáng),斷言等。 Java是一種編程語言,隨著時(shí)間的發(fā)展,可以滿足Java軟件開發(fā)人員的需求。 請(qǐng)注意,在運(yùn)行時(shí)以及支持庫,程序包,工具和實(shí)用程序等Java環(huán)境中,也添加和刪除了元素(分別為Java shell和Java applet。),但是這里的重點(diǎn)是Java,即編程語言。
Java的成功和流行使得它被用來教授編碼。 計(jì)算機(jī)科學(xué)AP(高級(jí)分班)考試使用Java。 Java的問題是一個(gè)悖論。 隨著Java的成功以及許多開發(fā)人員編寫Java代碼,那些對(duì)編程不熟悉的人和那些試圖學(xué)習(xí)編程的人都被遺忘了。
2.問題是編程中沒有程序
曾經(jīng)在1980年代和1990年代有抱負(fù)的開發(fā)人員開始學(xué)習(xí)使用無處不在的BASIC進(jìn)行編碼,然后轉(zhuǎn)移到Pascal(或FORTRAN,C),然后轉(zhuǎn)移到功能更強(qiáng)大的面向?qū)ο蟮恼Z言,例如Objective-C,C ++,Smalltalk,Java 。 在此過程中,過渡是從基本編程概念(例如變量與常量,輸入或輸出,if語句等)在對(duì)象,類上進(jìn)行的,然后到面向?qū)ο蟮脑砗驮O(shè)計(jì)模式的過渡。軟件開發(fā)人員的路徑。
但是,學(xué)習(xí)Java的新手或“新手”必須應(yīng)對(duì)眾多功能,這些功能要么被忽略,要么在使用時(shí)卻不知道該功能的用途。 這是“不關(guān)注窗簾背后的人”(綠野仙蹤)。 或Java的外來功能是又一個(gè)增加認(rèn)知超負(fù)荷的功能。 也就是說,“……教師同時(shí)向?qū)W習(xí)者提供太多信息或太多任務(wù),導(dǎo)致學(xué)習(xí)者無法處理此信息的情況。” [Brit 2019]這是一個(gè)神話,在這個(gè)神話中,新手無奈地將計(jì)算機(jī)扔到了窗外,然后失去了學(xué)習(xí)編碼的興趣。
3.計(jì)劃實(shí)體
因此,Java編程缺少程序?qū)嶓w來簡(jiǎn)單地編寫應(yīng)用程序或程序。 諸如BASIC和Pascal之類的較早的結(jié)構(gòu)化編程語言不過是程序?qū)嶓w。 因此,對(duì)于Java的復(fù)雜性,優(yōu)雅性和強(qiáng)大的功能,它缺少所有程序中最簡(jiǎn)單的功能。 考慮下面的經(jīng)典程序,但使用BASIC的簡(jiǎn)單程序,以讀取用戶名,然后打印問候語。 [Wiki 2019a] BASIC源代碼為:
10 PRINT "what is your name?" 20 INPUT "...(Enter Your Name)...", a$ 30 PRINT 40 PRINT "hello, "; a$; ", I am your computer, nice to meet you." 60 ENDJava源代碼中相同的BASIC程序是:
import java.util.Scanner; class WhatIsYourName {private WhatIsYourName(){}public static void main(String[] args){System.out.println("what is your name?");System.out.print("...(Enter Your Name)..."); String name = System.console().readLine();System.out.printf("hello, %s, I am your computer, nice to meet you.%n", name);System.exit(0); }//end main;}//end class WhatIsYourName相比之下,兩種編程語言都可以達(dá)到與程序相同的最終結(jié)果,讀取用戶名,然后向他們打印問候語。 但是,Java版本需要公開一些需要進(jìn)一步理解或忽略的細(xì)節(jié)。 考慮一下新手會(huì)問有關(guān)Java代碼的一些可能的問題:
4.一切面向?qū)ο?/h2>
使用Java的這種基本,簡(jiǎn)單的程序應(yīng)用程序需要許多面向?qū)ο蟮墓δ堋?再舉一個(gè)例子,考慮簡(jiǎn)單而臭名昭著的“ Hello,World !!!” 在BASIC與Java中。
4.1使用Zepton編程為Java
該說明性示例說明了對(duì)程序?qū)嶓w構(gòu)造的需求。 與類相似,不同之處在于程序是執(zhí)行或應(yīng)用程序的單元,而不是可重用的對(duì)象。 一個(gè)示例是相同的BASIC程序,但是用ZeptoN表示為程序而不是Java類:
prog WhatIsYourName { beginprintln("what is your name?");print("...(Enter Your Name)..."); String name = readLine();printf("hello, %s, I am your computer, nice to meet you.%n", name);exit(0);}//end prog WhatIsYourNameZeptoN程序更具可讀性,簡(jiǎn)單性和緊湊性。 ZeptoN轉(zhuǎn)編譯器[Gilr 2019b]將ZeptoN程序轉(zhuǎn)換為Java類時(shí),將自動(dòng)創(chuàng)建必要的main(String [] args)方法,以及一些提供默認(rèn)環(huán)境的“樣板”源代碼。
樣板源代碼只是包裝在公共靜態(tài)方法中的簡(jiǎn)單方法調(diào)用。 因此,“ System.out.println(…)”就是具有相同參數(shù)類型簽名的“ println(…)”。 或者,“ System.exit(…)”也就是具有相同參數(shù)類型的“ exit(…)”。
所需的導(dǎo)入語句將自動(dòng)生成。 總體而言,樣板源代碼中大約有70種方法和屬性。 一個(gè)重要的原則是ZeptoN的特定方法和屬性很少,并且方法名稱是相同的,并且具有相同的參數(shù)類型簽名。 因此,ZeptoN開發(fā)人員可以回到Java,或從Java遷移到ZeptoN,而不會(huì)遇到任何問題。
4.2 ZeptoN中的非標(biāo)準(zhǔn)方法
一種非標(biāo)準(zhǔn)靜態(tài)方法是“ String [] getArgs()”,該方法獲取命令行程序參數(shù)。 另一個(gè)是“ void nop()”,表示對(duì)存根方法沒有任何操作。 Java的語句為空,但是“ nop()”更為明確。 一些非標(biāo)準(zhǔn)常量是EMPTY_STRING,EMPTY_CHAR和NULL_CHAR。
再次將非標(biāo)準(zhǔn)方法和屬性保留為少數(shù),以避免混淆的Java源代碼。 標(biāo)準(zhǔn)方法是“ String readLine()”,但不需要使用Java Scanner,BufferedReader或其他類。 ZeptoN強(qiáng)調(diào)簡(jiǎn)潔性。 而且,作為ZeptoN的創(chuàng)建者,開發(fā)人員和第一個(gè)程序員,它總是使我很煩惱,String類沒有魔術(shù)常數(shù)EMPTY_STRING,而Character類沒有EMPTY_CHAR或NULL_CHAR。 我試圖保持邏輯,但我仍然……感到厭煩。 但是許多編程語言通常會(huì)根據(jù)他們的經(jīng)驗(yàn)而具有設(shè)計(jì)者的特質(zhì)。
4.3 ZeptoN的摘要
ZeptoN是Java,但是它將程序?qū)嶓w從程序?qū)嶓w反編譯為一個(gè)類,轉(zhuǎn)換main()方法,并添加一組與其他類中的方法和屬性類似的樣板方法和屬性。 從而創(chuàng)建供開發(fā)人員使用的默認(rèn)環(huán)境。 這很容易使用轉(zhuǎn)編譯器實(shí)現(xiàn),從而避免了完整的Java編譯器實(shí)現(xiàn)的開銷和復(fù)雜性。 反編譯器將ZeptoN編譯為Java,然后使用Java Compiler API編譯為字節(jié)碼。
對(duì)于特定的JDK版本,ZeptoN“自動(dòng)”具有這些功能。 因此,例如,如果使用JDK 13,則文本塊是ZeptoN中功能的一部分。 ZeptoN as Java包含Java的功能。 因此,對(duì)于Java的下一版本JDK 14,記錄可能是ZeptoN中的一項(xiàng)功能。
現(xiàn)在,由于ZeptoN是基本的反編譯器,因此可以擴(kuò)展ZeptoN以添加其他功能,然后再將這些功能反編譯為Java。 目標(biāo)是一致地添加這種功能,但也要避免完整的編譯器實(shí)現(xiàn)。 幸運(yùn)的是,Java具有一組功能豐富的軟件包和類,這些軟件包和類可以通過一些工作和富有創(chuàng)意的思想來實(shí)現(xiàn)。
5.擴(kuò)展ZeptoN
原始類型有時(shí)會(huì)在編寫Java以及擴(kuò)展ZeptoN方面引起皺紋。 因此,該功能是在ZeptoN中將原始類型自動(dòng)轉(zhuǎn)換為類包裝器類型。 從原始類型自動(dòng)轉(zhuǎn)換為對(duì)象形式(我稱之為“提升為對(duì)象”)的這一功能可以使用轉(zhuǎn)編譯器輕松實(shí)現(xiàn)。 這些論點(diǎn)都主張使用原始類型支持[Moor 2014]和反對(duì)[Alpe 2000]。 最好的方法是讓開發(fā)人員在用ZeptoN編寫源代碼時(shí)有這種選擇。
5.1基本類型
Java語言規(guī)范Java SE 13版[Orac 2019]將原語類型定義為“原語類型由Java編程語言預(yù)定義并由其reserved關(guān)鍵字命名。” 更具描述性的定義是原始類型,它是Java編程語言中預(yù)定義的數(shù)據(jù)。 類型“ null”和“ void”不在原始類型中。
Null是默認(rèn)引用值,或“ null類型具有一個(gè)值,null引用,由null文字null表示”。[Orac 2019] void類型指示非返回值方法,或“在方法聲明和定義中使用若要指定該方法不返回任何類型,則該方法返回void。 它不是一種類型,并且沒有C / C ++中的無效引用/指針。” [Wiki 2019b]
由于ZeptoN是Java,因此可以得出以下結(jié)論:基本類型完全相似。
5.2對(duì)象包裝器類型
基本類型是有效的,但是Java中的一個(gè)“皺紋”不是對(duì)象。 沒有引用原始類型,沒有任何對(duì)象或狀態(tài)。 但是對(duì)象類型有時(shí)是必要且有用的。 因此,Java提供了對(duì)象包裝器類型來使原語對(duì)象化。
Eckel [Ecke 2003]將對(duì)象類型包裝器描述為:“原始數(shù)據(jù)類型的“包裝器”類允許您在堆上創(chuàng)建一個(gè)非原始對(duì)象來表示該原始類型。”
例如,要將原始類型與任何Java集合一起使用,則需要將原始類型作為對(duì)象類型。 Java具有自動(dòng)將原始類型提升為對(duì)象類型包裝器的功能。
5.3自動(dòng)裝箱性能
具有自動(dòng)裝箱的功能(因?yàn)閆eptoN中使用Java 5),但是更簡(jiǎn)單的方法是簡(jiǎn)單地將所有原始類型提升為對(duì)象。 Java在大多數(shù)原語之間使用自動(dòng)裝箱(null和void除外),但是在原語類型(例如,簡(jiǎn)單為datum)和包裝類型Integer(作為對(duì)象)之間沒有聯(lián)系。
另一個(gè)重要的考慮因素是性能,對(duì)自動(dòng)裝箱的無限制使用和未考慮使用都可能導(dǎo)致Java字節(jié)碼出現(xiàn)性能問題。 升級(jí)為對(duì)象的此功能的最大優(yōu)點(diǎn)之一是編寫的代碼更少,源代碼更干凈。
無效和無效這兩個(gè)原始類型不是基準(zhǔn),因此不會(huì)提升為對(duì)象。 布爾,字節(jié),字符,雙精度型,浮點(diǎn)型,整型,長(zhǎng)型和短型這8種原始類型被提升為對(duì)象。 但是與原始類型相比,對(duì)象類型將使用更多的內(nèi)存。
5.4用原始類型轉(zhuǎn)譯ZeptoN源
考慮以下簡(jiǎn)單的ZeptoN程序“ polyMathPrimitive1.zep”,該程序根據(jù)for循環(huán)(因此為多項(xiàng)式)中的索引來計(jì)算數(shù)字,但使用原始類型int進(jìn)行計(jì)算。 靜態(tài)方法“ polyMathLoop”用作從程序塊調(diào)用的方法。
package javacodegeeks; prog polyMathPrimitive1 {static void polyMathLoop(final int loopLimit){for (int index = 0; index < loopLimit; index++) {int number = index * index * index + index * index + index; }//end for}//end polyMathLoopbeginlong timeStart = nanoTime();polyMathLoop(1000);long timeClose = nanoTime();printf("Total time: %d nanosec%n",(timeClose-timeStart)); println();exit(0); }使用整數(shù)常量1000調(diào)用polyMathLoop()方法。除了重復(fù)計(jì)算相同的多項(xiàng)式之外,該方法實(shí)際上不做任何事情。
使用ZeptoN編譯器進(jìn)行編譯時(shí),然后運(yùn)行:
/Users/williamgilreath$java -cp . Zep polyMathPrimitive.zep /Users/williamgilreath$java -cp . javacodegeeks.polyMathPrimitive1 Total time: 18484 nanosecZeptoN程序“ polyMathObject.zep”說明了等效的ZeptoN在編譯時(shí)為:
package javacodegeeks; prog polyMathObject {static void polyMathLoop(final Integer loopLimit){for (Integer index = 0; index < loopLimit; index++) {Integer number = index * index * index + index * index + index; }//end for}//end polyMathLoopbeginlong timeStart = nanoTime();polyMathLoop(1000);long timeClose = nanoTime();printf("Total time: %d nanosec%n",(timeClose-timeStart)); println();exit(0);}使用ZeptoN編譯器進(jìn)行編譯時(shí),然后運(yùn)行:
/Users/williamgilreath$java -cp . ZepC polyMathObject.zep /Users/williamgilreath$java -cp . javacodegeeks.polyMathObject Total time: 512084 nanosec兩個(gè)性能時(shí)間的比率表明總比率為1:27.7。 顯然,將每個(gè)原語完全升級(jí)為對(duì)象類型可能會(huì)對(duì)性能造成問題。
考慮一種替代方法,其中ZeptoN程序中并非每個(gè)整數(shù)都是原始int或?qū)ο蟀bInteger。 ZeptoN源代碼為:
package javacodegeeks; prog polyMathPrimitive2 {static void polyMathLoop(final Integer loopLimit){ for (int index = 0; index < loopLimit; index++) {int number = index * index * index + index * index + index; }//end for}//end polyMathLoopbeginlong timeStart = nanoTime();polyMathLoop(1000);long timeClose = nanoTime();printf("Total time: %d nanosec%n",(timeClose-timeStart)); println();exit(0); }使用ZeptoN編譯器進(jìn)行編譯時(shí),然后運(yùn)行:
/Users/williamgilreath$java -cp . Zep polyMathPrimitive2.zep /Users/williamgilreath$java -cp . javacodegeeks.polyMathPrimitive2 Total time: 92350 nanosec表演時(shí)間的比例表明總體比例為1:5的差異。 與純對(duì)象包裝類型實(shí)現(xiàn)相比,這是性能上的改進(jìn)。 混合方法的性能更高。
5.5“促銷到對(duì)象”的功能語法
之前和之后的示例說明了從原始int到對(duì)象包裝的轉(zhuǎn)換Integer是全部或全部。 性能顯然會(huì)受到極大影響。 但是,在某些情況下,開發(fā)人員想要指定原始類型仍然是原始類型,尤其是在性能指標(biāo)上。 這反映了前述方法的特點(diǎn),即為開發(fā)人員提供了基本類型或?qū)ο箢愋偷倪x擇。
語法是從原始類型升級(jí)為對(duì)象類型的一種排斥。 對(duì)于語法,沒有任何其他指示符的普通原語被提升為對(duì)象類型。 因此,int變成Integer,double變成Double,依此類推。
排除語法是從JavaCC [ref]語法中“借用”的,用于表達(dá)語法規(guī)則,正如Copeland [Cope 2009]解釋的那樣,“……是嗎? 量詞,它與指定模式的零個(gè)或一次匹配。”
從提升為對(duì)象類型中排除的原始類型具有字符“?”的結(jié)尾“鉤”或“問號(hào)”。 在標(biāo)識(shí)符之后指示轉(zhuǎn)編譯器不要將原始類型提升為對(duì)象類型。 帶有“?”字符 原始類型仍然是原始類型。 因此是“ int?” 被編譯為“ int”而不是“ Integer”,因?yàn)闆]有提升對(duì)象類型。
重寫原始類型和對(duì)象類型的原始混合語法,ZeptoN源代碼中的此語法為:
package javacodegeeks;prog polyMathSyntax {static void polyMathLoop(final int loopLimit){for (int? index = 0; index < loopLimit; index++) {int? number = index * index * index + index * index + index;}//end for}//end polyMathLoopbeginlong? timeStart = nanoTime();polyMathLoop(1000);long? timeClose = nanoTime();printf("Total time: %d nanosec%n",(timeClose-timeStart)); println();exit(0); }從語法重新編譯為通用Java源代碼后,“ polyMathSyntax.zep” ZeptoN程序等效于“ polyMathPrimitive2.zep” ZeptoN程序。
該語法允許開發(fā)人員選擇是將基元保留為基元類型,還是提升為對(duì)象類型包裝器。 因此,開發(fā)人員處于控制之中,而不是ZeptoN反編譯器。 語法有點(diǎn)熟悉,類似于JavaCC生產(chǎn)規(guī)則,Kotlin的語法用于允許的無效值,Swift的語法用于nil。 因此,盡管語義完全不同,但語法還是有些熟悉。
6.功能語法的Transpiler
指定原始類型的語法很簡(jiǎn)單,很熟悉,仍然保持原始。 問題是如何在反編譯器中實(shí)現(xiàn)此功能,以便將ZeptoN反編譯為Java源代碼。 但是ZeptoN轉(zhuǎn)編譯器已經(jīng)將ZeptoN源代碼轉(zhuǎn)換為Java源代碼,然后使用Java Compiler API對(duì)其進(jìn)行編譯。
轉(zhuǎn)換功能語法的軟件實(shí)現(xiàn)面臨兩個(gè)挑戰(zhàn):
這是經(jīng)典的軟件開發(fā)工程師的任務(wù)-在現(xiàn)有的舊版軟件中實(shí)現(xiàn)功能。 簡(jiǎn)而言之,創(chuàng)建一個(gè)新算法,然后在ZeptoN轉(zhuǎn)編譯器的舊版代碼中實(shí)現(xiàn)。
6.1特征算法
從基本類型到對(duì)象類型的特征的算法很簡(jiǎn)單,與任何更復(fù)雜的編譯相比,它更具有正則表達(dá)式的搜索和替換過程。
該算法分為三個(gè)步驟:
算法的每個(gè)步驟然后依次處理下一步中的字符串,直到將具有語法功能的原始ZeptoN源轉(zhuǎn)換為具有原始類型和對(duì)象類型的ZeptoN源代碼。
6.1.1將原語重命名為中間標(biāo)識(shí)符
該算法的第一步是保留要保留的基本體。 但是重命名是必需的,以避免搜索并替換為對(duì)象包裝器類型。 可以使用任何不同的替換,但是將原始字符的大寫字母與字母'Q'串聯(lián)在一起可以簡(jiǎn)化要編寫的代碼,因?yàn)槊總€(gè)原始標(biāo)識(shí)符都可以在搜索中使用,并可以用正則表達(dá)式替換。
6.1.2重命名原語為對(duì)象類型包裝器
中間步驟是在ZeptoN源代碼中搜索原始類型標(biāo)識(shí)符并將其替換為對(duì)象類型標(biāo)識(shí)符。 檢查并替換每個(gè)原始標(biāo)識(shí)符。 因此,原語保持原語并在算法的最后一步中恢復(fù)。
6.1.3重命名中間標(biāo)識(shí)符為原始類型
該算法的最后一步將還原已重命名的原始類型。 使用唯一的,不相同的標(biāo)識(shí)符,將替換原始類型標(biāo)識(shí)符而不會(huì)在末尾添加問號(hào),并且在ZeptoN源代碼中,指示為在語法中保持原始的原始語言也是如此。
6.2功能語法的實(shí)現(xiàn)
該算法可以在一系列原始類型上使用三個(gè)for循環(huán)來實(shí)現(xiàn),甚至可以更簡(jiǎn)單地使用臭名昭著的“一個(gè)內(nèi)襯”來實(shí)現(xiàn),后者更像是使用一個(gè)for循環(huán)的流。 因此,使用原始類型來轉(zhuǎn)換ZeptoN源代碼字符串以提升并保留在基本ZeptoN源代碼中的Java源代碼就是“ transpileCode()”方法:
public static String transpileCode(final String zepCode){ String result = zepCode;final String[] primitiveList = new String[]{"boolean", "byte", "char", "double", "float", "int", "long", “short" };final String[] objectTypeList = new String[]{"Boolean", "Byte", "Character", "Double", "Float", "Integer", "Long", “Short" };for(int x=0;x<primitiveList.length;x++){//primitive type with '?' at endString prim = String.format("%s[?]", primitiveList[x]); if(result.contains(primitiveList[x])){//primitive type to uppercaseString upper = String.format("%SQ", primitiveList[x]);//exact match of primitive typeString result = result . replaceAll(prim, upper). replaceAll(type, objectTypeList[x]) . replaceAll(upper, primitiveList[x]);}//end if}//end forreturn result; }//end transpileCode6.3轉(zhuǎn)換然后導(dǎo)出到文件
在“ transpileCode()”方法將特征語法轉(zhuǎn)換為ZeptoN源代碼之后,然后將源代碼寫入外部文件。 整體“ transpile()”方法的源代碼為:
private static void transpile(String fileNameOrig) { String srcCode = "";try {srcCode = new String(Files.readAllBytes(Paths.get(fileNameOrig))); } catch (Exception ex) {System.out.printf("Failure reading source file: %s!%n", fileNameOrig);return; }//end try//transpile to ZeptoN source from extended feature syntax srcCode = transpileCode(srcCode);String path = fileNameOrig.replace(".orig", ".zep");try {Files.write(Paths.get(path), srcCode.getBytes(Charset.defaultCharset()));} catch (Exception ex) {System.out.printf("Source code write failure!%n"); return;}//end try}//end transpile“ transpile()”方法使用外部文件,“。zep”文件中的新功能語法變?yōu)椤?.orig”文件。 將源代碼文件讀入字符串,然后轉(zhuǎn)換為ZeptoN源代碼。 然后將ZeptoN源代碼文件寫入“ .zep”文件。 這將保留傳遞的原始文件參數(shù)以及任何命令行參數(shù)參數(shù)。 其余編譯器使用現(xiàn)有的ZeptoN轉(zhuǎn)編譯器實(shí)現(xiàn)。
7.使用ZeptoN的轉(zhuǎn)編譯器實(shí)現(xiàn)
ZeptoN轉(zhuǎn)編譯器用作轉(zhuǎn)編譯器的舊版或預(yù)先存在的代碼,以集成新功能語法。 方法是:
因此,具有ZeptoN中功能語法的新轉(zhuǎn)編譯器將使用外部文件,因此不會(huì)在內(nèi)部進(jìn)行編譯。 這樣做的好處是,在使用新語法對(duì)ZeptoN源代碼進(jìn)行預(yù)處理之后,可以將中間ZeptoN源代碼存儲(chǔ)為整個(gè)編譯過程的一部分。
現(xiàn)有的ZeptoN反編譯器(使用內(nèi)存中的Java編譯器將反編譯的ZeptoN編譯為Java源代碼)用作包或庫。 因此,現(xiàn)有的ZeptoN編譯器不會(huì)被修改或細(xì)分,而是在編譯的最后階段使用。
7.1壓縮現(xiàn)有的ZeptoN Transcompiler
現(xiàn)有的ZeptoN轉(zhuǎn)編譯器“ Zep.java”是在Github存儲(chǔ)庫中發(fā)布的開源Java。 轉(zhuǎn)編譯器在內(nèi)部將文件“ source.zep”中的ZeptoN源代碼轉(zhuǎn)換為Java源代碼,然后使用Java Compiler API內(nèi)存將其編譯為字節(jié)碼.class文件。
Transcompiler Zep.java類的兩個(gè)核心方法當(dāng)然是“ main(String [] args)”作為調(diào)用的主要方法,以及“ compile(String [] args)”方法進(jìn)行實(shí)際的反編譯,然后編譯為Java字節(jié)碼.class文件。 問題是將原始類型轉(zhuǎn)換為對(duì)象包裝器類型后要調(diào)用哪種方法。 這兩個(gè)方法是“ main()”方法或“ compile()”方法,它們都是靜態(tài)的無狀態(tài)方法。
7.1.1 main()方法
ZeptoN轉(zhuǎn)編譯器“ Zep.java”具有可以使用的“ main()”方法,因?yàn)樗袇?shù)均已保留,并且使用了外部文件。 “ main()”方法的源代碼是:
public static void main(final String[] args) {try {if (args.length == 0) {System.out.printf("%s %s%n%s%n", RELEASE, VERSION, LICENSE); }//end ifZep.compile(args);} catch(Exception ex) {error("ZeptoN Compiler Exception: '%s' is '%s'.%n",ex.getClass().getName(), ex.getMessage()); ex.printStackTrace();System.exit(EXIT_CODE_FAILURE); }//end trySystem.exit(EXIT_CODE_SUCCESS); }//end main通過“ main”調(diào)用ZeptoN Transcompiler會(huì)遇到棘手的問題,因?yàn)槌晒蚴《紩?huì)調(diào)用“ System.exit()”。 因此,不可能使用新的語法功能編譯多個(gè)文件,因?yàn)榫幾g的第一個(gè)文件將在成功或失敗時(shí)終止。
7.1.2 compile()方法
ZeptoN轉(zhuǎn)編譯器方法“ compile()”由“ main()”方法調(diào)用。 該方法創(chuàng)建ZeptoN編譯器的實(shí)例,處理命令行參數(shù),并配置命令行參數(shù)。 如果沒有傳遞參數(shù),或沒有文件提供給轉(zhuǎn)編譯器,則會(huì)引發(fā)錯(cuò)誤。
ZeptoN轉(zhuǎn)編譯器的“ compile()”方法的源代碼為:
public static void compile(final String[] args) {if (args.length == 0) { error(ERROR_NO_INPUT);}//end iffinal Zep comp = new Zep();comp.processCommandLineArgs(args);if (files.isEmpty()) { error(ERROR_NO_FILES);}//end ifcomp.configureParams();for (String sourceFile : files) {comp.compileZeptoN( Zep.transpile(sourceFile), sourceFile );}//end for }//end compile實(shí)際的ZeptoN轉(zhuǎn)編譯器使用“ transpile()”方法返回Java源文件對(duì)象,該對(duì)象將傳遞給編譯器實(shí)例方法“ compileZeptoN()”以生成Java字節(jié)碼.class文件。 “ transpile()”方法將外部ZeptoN源文件讀取為String對(duì)象,并轉(zhuǎn)換為Java源代碼,然后對(duì)其進(jìn)行編譯。
7.1.3調(diào)用compile()方法
“ compile()”方法用于將已轉(zhuǎn)換的功能語法編譯為字節(jié)碼.class文件。 由于使用了外部文件,因此可能有兩個(gè)錯(cuò)誤:
重命名文件,然后將新語法功能轉(zhuǎn)換為ZeptoN源代碼后,將調(diào)用ZeptoN轉(zhuǎn)編譯器“ compile()”,然后ZeptoN轉(zhuǎn)編譯器將完成轉(zhuǎn)碼為Java字節(jié)碼.class文件的工作。
之后,在刪除中間的“ .zep”文件后,將重命名文件“ .orig”中具有新功能語法的原始源代碼文件。 “ compile()”方法中此步驟的源代碼為:
private static void compile(String[] args) { //...Zep.compile(args);for(String fileName : fileList) { Path path = Paths.get(fileName); try {Files.delete(path); } catch (Exception ex) {System.out.printf("Failure deleting file path:%s!%n", path);}//end tryString fileNameOrig = fileName.replace(".zep", ".orig");Path oldFile = Paths.get(fileNameOrig); Path newFile = Paths.get(fileName);try {Files.move(oldFile, newFile, StandardCopyOption.REPLACE_EXISTING); } catch (Exception ex) {System.out.printf("Error: Unable to rename file %s!%n", oldFile); }//end try}//end for}//end transpile成功刪除中間文件并將“ .orig”源代碼文件重命名為“ .zep”后,反編譯過程即告完成。
7.1.4擴(kuò)展功能語法轉(zhuǎn)譯器摘要
將新語法功能轉(zhuǎn)換為Java字節(jié)碼.class文件的整個(gè)過程使用外部文件,因此大部分過程是重命名,刪除,讀取和寫入源代碼文件。 但是所有這些數(shù)據(jù)移動(dòng)都允許使用帶有編譯器參數(shù)和文件名的“ compile()”來調(diào)用現(xiàn)有的ZeptoN轉(zhuǎn)編譯器。 整個(gè)過程是:
7.2測(cè)試新的語法功能
新語法功能的實(shí)現(xiàn)已完成,但是現(xiàn)在可以測(cè)試ZeptoN編程語言中添加的新功能。
測(cè)試新的語法功能將使用四個(gè)ZeptoN源文件。 使用原始的ZeptoN編譯器,該測(cè)試很簡(jiǎn)單: 以及改良的ZeptoN編譯器:ZepPTO。 測(cè)試中使用的ZeptoN源代碼文件是:
Zep原始的ZeptoN源代碼編譯器將編譯所有ZeptoN源文件,但包含新功能語法的'polyMathSyntax.zep'除外。 ZepPTO擴(kuò)展的特色語法編譯器將編譯所有文件。
由于除“ polyMathSyntax.zep”以外的所有文件都將編譯,否則該文件將因Zep反編譯器而失敗,但因ZepPTO反編譯器而成功,因此使用此文件的輸出進(jìn)行比較,以避免不必要的重復(fù)和解釋。
7.2.1使用ZeptoN編譯新語法
當(dāng)使用ZeptoN轉(zhuǎn)編譯器進(jìn)行編譯時(shí),結(jié)果為:
圖1:ZeptoN編譯器錯(cuò)誤有11個(gè)錯(cuò)誤,主要與新語法有關(guān),不足為奇,因?yàn)楝F(xiàn)有的ZeptoN轉(zhuǎn)編譯器尚未實(shí)現(xiàn)新語法功能。
7.2.2使用ZepPTO的轉(zhuǎn)編譯器
使用新的ZepPTO(提升為對(duì)象)轉(zhuǎn)編譯器進(jìn)行編譯時(shí),結(jié)果為:
/Users/williamgilreath$java javacodegeeks.zepton.ZepPTO -echo polyMathSyntax.zep ZeptoN Compiler Options: [-d, /Users/williamgilreath, -g] Files: [polyMathSyntax.zep] Encoding: UTF-8 ZeptoN Compiler result for file: 'polyMathSyntax.zep' is: Success.現(xiàn)在運(yùn)行生成的Java字節(jié)碼.class文件,結(jié)果是:
/Users/williamgilreath$java -cp . javacodegeeks.polyMathSyntax Total time: 301515 nanosec將ZeptoN源代碼轉(zhuǎn)換為字節(jié)碼.class文件可使用Java運(yùn)行時(shí)運(yùn)行。
7.2.3使用Zep編譯其他文件
其他具有常規(guī)ZeptoN語法的ZeptoN源文件是使用未擴(kuò)展的ZeptoN轉(zhuǎn)編譯器“ Zep”和參數(shù)“ -echo”來編譯的,以回顯所使用的Javac參數(shù)以及編譯器的整體成功或失敗。
/Users/williamgilreath$java io.github.wgilreath.ZeptoN.Zep -echo polyMathObject.zep ZeptoN Compiler Options: [-d, /Users/williamgilreath, -g] Files: [polyMathObject.zep] Encoding: UTF-8 ZeptoN Compiler result for file: 'polyMathObject.zep' is: Success.常規(guī)的ZeptoN編譯器已成功編譯ZeptoN源文件“ polyMathObject.zep”。
/Users/williamgilreath$java io.github.wgilreath.ZeptoN.Zep -echo polyMathPrimitive1.zep ZeptoN Compiler Options: [-d, /Users/williamgilreath, -g] Files: [polyMathPrimitive1.zep] Encoding: UTF-8 ZeptoN Compiler result for file: 'polyMathPrimitive1.zep' is: Success.常規(guī)的ZeptoN編譯器已成功編譯ZeptoN源文件“ polyMathPrimitive1.zep”。
/Users/williamgilreath$java io.github.wgilreath.ZeptoN.Zep -echo polyMathPrimitive2.zep ZeptoN Compiler Options: [-d, /Users/williamgilreath, -g] Files: [polyMathPrimitive2.zep] Encoding: UTF-8 ZeptoN Compiler result for file: 'polyMathPrimitive2.zep' is: Success.常規(guī)的ZeptoN編譯器已成功編譯ZeptoN源文件“ polyMathPrimitive2.zep”。
7.2.4使用ZepPTO編譯其他文件
其他具有常規(guī)ZeptoN語法的ZeptoN源文件將通過擴(kuò)展的ZeptoN轉(zhuǎn)編譯器“ ZepPTO”與參數(shù)“ -echo”一起進(jìn)行編譯,以回顯所使用的Javac參數(shù)以及編譯器的整體成敗。
/Users/williamgilreath$java javacodegeeks.zepton.ZepPTO -echo polyMathObject.zep ZeptoN Compiler Options: [-d, /Users/williamgilreath, -g] Files: [polyMathObject.zep] Encoding: UTF-8 ZeptoN Compiler result for file: 'polyMathObject.zep' is: Success.擴(kuò)展的ZeptoN編譯器已成功編譯ZeptoN源文件“ polyMathObject.zep”。
/Users/williamgilreath$java javacodegeeks.zepton.ZepPTO -echo polyMathPrimitive1.zep ZeptoN Compiler Options: [-d, /Users/williamgilreath, -g] Files: [polyMathPrimitive1.zep] Encoding: UTF-8 ZeptoN Compiler result for file: 'polyMathPrimitive1.zep' is: Success.擴(kuò)展的ZeptoN編譯器已成功編譯ZeptoN源文件“ polyMathPrimitive1.zep”。
/Users/williamgilreath$java javacodegeeks.zepton.ZepPTO -echo polyMathPrimitive2.zep ZeptoN Compiler Options: [-d, /Users/williamgilreath, -g] Files: [polyMathPrimitive2.zep] Encoding: UTF-8 ZeptoN Compiler result for file: 'polyMathPrimitive2.zep' is: Success.擴(kuò)展的ZeptoN編譯器已成功編譯ZeptoN源文件“ polyMathPrimitive2.zep”。
7.2.5測(cè)試總結(jié)
通過兩個(gè)轉(zhuǎn)編譯器對(duì)常規(guī)ZeptoN源文件和擴(kuò)展語法功能的測(cè)試表明,擴(kuò)展轉(zhuǎn)編譯器ZepPTO可編譯為Java字節(jié)碼.class文件。 新功能語法可將基本類型提升為對(duì)象類型包裝程序,并使用新功能語法排除基本類型以保持基本類型。
8.結(jié)論
ZeptoN編程語言是Java,僅關(guān)注程序?qū)嶓w,這是Java編程語言所缺乏的功能。 這將創(chuàng)建一種與Java語法相似且兼容的編程語言。 這樣的編程語言可以輕松地反編譯為Java源代碼,然后使用Java Compiler API編譯為字節(jié)碼.class文件。
ZeptoN編程語言通過添加具有新語法的新功能進(jìn)行了擴(kuò)展。 此功能是將原始類型(不包括null和void)轉(zhuǎn)換為對(duì)象包裝器類型。 這是編程語言的一個(gè)常見主題,通常在極端情況下被稱為“蠕動(dòng)性胎炎”或“特征蠕變”。 但是,對(duì)于編程語言語法中的新功能,必須對(duì)其進(jìn)行設(shè)計(jì)和實(shí)現(xiàn)。
新功能語法是通過使用將新功能語法的ZeptoN源代碼轉(zhuǎn)換為普通ZeptoN源代碼的轉(zhuǎn)編譯器來實(shí)現(xiàn)的。 使用現(xiàn)有的ZeptoN反編譯器將源代碼反編譯為Java字節(jié)碼。 這具有將現(xiàn)有的Transcompiler用于ZeptoN的優(yōu)點(diǎn),但是可以通過新功能自定義和擴(kuò)展語言。 這樣可以避免對(duì)ZeptoN中添加的新語法功能進(jìn)行全新的實(shí)現(xiàn)
因此,重點(diǎn)是實(shí)現(xiàn)針對(duì)新語法功能的編譯器,然后實(shí)施,利用現(xiàn)有的編譯器和編譯器,因?yàn)閆eptoN編譯器先編譯為Java源代碼,然后再編譯為Java字節(jié)碼.class文件。 可以使用相同的方法來通過新功能擴(kuò)展Java,使用WEJAC編譯器[Gilr 2019b]將轉(zhuǎn)編譯后的Java源代碼編譯為純Java源代碼,然后編譯為字節(jié)碼.class文件。
9.參考
[Alpe 2000] Alpert,ShermanR。“原始類型被認(rèn)為有害”。
英國(guó)文化協(xié)會(huì),《 更多的Java寶石》 ,劍橋大學(xué)出版社,紐約,紐約,2000年,第435-454頁。[英國(guó)2019年]。
“認(rèn)知超載”,2015年5月20日, https://www.teachingenglish.org.uk/article/cognitive-overload 。
于2019年11月9日訪問。[Cope 2009] Tom Copeland。
用JavaCC生成解析器 ,《百年紀(jì)念書》,弗吉尼亞州亞歷山大市,2009年,第29頁。[Ecke 2003] Eckel,Bruce。
《用Java思考》 ,Prentice-Hall,上薩德爾河,新澤西州,2003年,第3頁。
90 [Gilr 2019a] Gilreath,William F.GitHub存儲(chǔ)庫“ WEJAC:Will's Elided Java API編譯器,'' https ://wgilreath.github.io/WEJAC/.2019年12月31日訪問。[Gilr2019b] Gilreath,William F.GitHub存儲(chǔ)庫“ ZepC – ZeptoN Echo Transcompiler”, https: //wgilreath.github.io/ZeptoN/于2019年12月31日訪問。[Moor 2014] Moore,John。
“ Java中保留原語的案例”,JavaWorld, https: //www.javaworld.com/article/2150208/a-case-for-keeping-primitives-in-java.html。
2014年5月。于2019年12月27日訪問。[Orac 2019] Oracle America,Inc.,Java語言規(guī)范,第13版, https: //docs.oracle.com/javase/specs/jls/se13/jls13.pdf。
訪問于2019年12月27日。[Wiki 2019a] Wikibooks,Java編程。
WikiBooks Edition, https ://en.wikibooks.org/wiki/Java_Programming/Keywords/void。
于2019年12月30日訪問。[Wiki 2019b] Wikibooks。
BASIC編程,2019年10月13日.https ://en.wikibooks.org/wiki/BASIC_Programming/Beginning_BASIC/User_Input,2019年11月9日訪問。
10.下載源代碼
下載您可以在此處下載此示例的完整源代碼: ZeptoN正在將程序放入Java中
翻譯自: https://www.javacodegeeks.com/zepton-is-putting-program-into-java.html
總結(jié)
以上是生活随笔為你收集整理的ZeptoN正在将程序放入Java的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一纳米等于多少米 一纳米是多少米
- 下一篇: java工程师的终极书单_Java 9