1.简介

Java编程语言或“ Java”于1995年引入。然而,在近25年的时间里,它增加了最初不是核心语言所具有的功能。 此类功能包括枚举,泛型,对基本C样式功能开关语句的许多增强,断言等。 Java是一种编程语言,随着时间的发展,可以满足Java软件开发人员的需求。 请注意,在运行时以及支持库,程序包,工具和实用程序等Java环境中,也添加和删除了元素(分别为Java shell和Java applet。),但是这里的重点是Java,即编程语言。

Java的成功和流行使得它被用来教授编码。 计算机科学AP(高级分班)考试使用Java。 Java的问题是一个悖论。 随着Java的成功以及许多开发人员编写Java代码,那些对编程不熟悉的人和那些试图学习编程的人都被遗忘了。

2.问题是编程中没有程序

曾经在1980年代和1990年代有抱负的开发人员开始学习使用无处不在的BASIC进行编码,然后转移到Pascal(或FORTRAN,C),然后转移到功能更强大的面向对象的语言,例如Objective-C,C ++,Smalltalk,Java 。 在此过程中,过渡是从基本编程概念(例如变量与常量,输入或输出,if语句等)在对象,类上进行的,然后到面向对象的原理和设计模式的过渡。软件开发人员的路径。

但是,学习Java的新手或“新手”必须应对众多功能,这些功能要么被忽略,要么在使用时却不知道该功能的用途。 这是“不关注窗帘背后的人”(绿野仙踪)。 或Java的外来功能是又一个增加认知超负荷的功能。 也就是说,“……教师同时向学习者提供太多信息或太多任务,导致学习者无法处理此信息的情况。” [Brit 2019]这是一个神话,在这个神话中,新手无奈地将计算机扔到了窗外,然后失去了学习编码的兴趣。

3.计划实体

因此,Java编程缺少程序实体来简单地编写应用程序或程序。 诸如BASIC和Pascal之类的较早的结构化编程语言不过是程序实体。 因此,对于Java的复杂性,优雅性和强大的功能,它缺少所有程序中最简单的功能。 考虑下面的经典程序,但使用BASIC的简单程序,以读取用户名,然后打印问候语。 [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 END

Java源代码中相同的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

相比之下,两种编程语言都可以达到与程序相同的最终结果,读取用户名,然后向他们打印问候语。 但是,Java版本需要公开一些需要进一步理解或忽略的细节。 考虑一下新手会问有关Java代码的一些可能的问题:

  1. 什么是课程?
  2. 什么是构造函数?
  3. 什么是空方法?

4.一切面向对象

使用Java的这种基本,简单的程序应用程序需要许多面向对象的功能。 再举一个例子,考虑简单而臭名昭著的“ Hello,World !!!” 在BASIC与Java中。

4.1使用Zepton编程为Java

该说明性示例说明了对程序实体构造的需求。 与类相似,不同之处在于程序是执行或应用程序的单元,而不是可重用的对象。 一个示例是相同的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 WhatIsYourName

ZeptoN程序更具可读性,简单性和紧凑性。 ZeptoN转编译器[Gilr 2019b]将ZeptoN程序转换为Java类时,将自动创建必要的main(String [] args)方法,以及一些提供默认环境的“样板”源代码。

样板源代码只是包装在公共静态方法中的简单方法调用。 因此,“ System.out.println(…)”就是具有相同参数类型签名的“ println(…)”。 或者,“ System.exit(…)”也就是具有相同参数类型的“ exit(…)”。

所需的导入语句将自动生成。 总体而言,样板源代码中大约有70种方法和属性。 一个重要的原则是ZeptoN的特定方法和属性很少,并且方法名称是相同的,并且具有相同的参数类型签名。 因此,ZeptoN开发人员可以回到Java,或从Java迁移到ZeptoN,而不会遇到任何问题。

4.2 ZeptoN中的非标准方法

一种非标准静态方法是“ String [] getArgs()”,该方法获取命令行程序参数。 另一个是“ void nop()”,表示对存根方法没有任何操作。 Java的语句为空,但是“ nop()”更为明确。 一些非标准常量是EMPTY_STRING,EMPTY_CHAR和NULL_CHAR。

再次将非标准方法和属性保留为少数,以避免混淆的Java源代码。 标准方法是“ String readLine()”,但不需要使用Java Scanner,BufferedReader或其他类。 ZeptoN强调简洁性。 而且,作为ZeptoN的创建者,开发人员和第一个程序员,它总是使我很烦恼,String类没有魔术常数EMPTY_STRING,而Character类没有EMPTY_CHAR或NULL_CHAR。 我试图保持逻辑,但我仍然……感到厌烦。 但是许多编程语言通常会根据他们的经验而具有设计者的特质。

4.3 ZeptoN的摘要

ZeptoN是Java,但是它将程序实体从程序实体反编译为一个类,转换main()方法,并添加一组与其他类中的方法和属性类似的样板方法和属性。 从而创建供开发人员使用的默认环境。 这很容易使用转编译器实现,从而避免了完整的Java编译器实现的开销和复杂性。 反编译器将ZeptoN编译为Java,然后使用Java Compiler API编译为字节码。

对于特定的JDK版本,ZeptoN“自动”具有这些功能。 因此,例如,如果使用JDK 13,则文本块是ZeptoN中功能的一部分。 ZeptoN as Java包含Java的功能。 因此,对于Java的下一版本JDK 14,记录可能是ZeptoN中的一项功能。

现在,由于ZeptoN是基本的反编译器,因此可以扩展ZeptoN以添加其他功能,然后再将这些功能反编译为Java。 目标是一致地添加这种功能,但也要避免完整的编译器实现。 幸运的是,Java具有一组功能丰富的软件包和类,这些软件包和类可以通过一些工作和富有创意的思想来实现。

5.扩展ZeptoN

原始类型有时会在编写Java以及扩展ZeptoN方面引起皱纹。 因此,该功能是在ZeptoN中将原始类型自动转换为类包装器类型。 从原始类型自动转换为对象形式(我称之为“提升为对象”)的这一功能可以使用转编译器轻松实现。 这些论点都主张使用原始类型支持[Moor 2014]和反对[Alpe 2000]。 最好的方法是让开发人员在用ZeptoN编写源代码时有这种选择。

5.1基本类型

Java语言规范Java SE 13版[Orac 2019]将原语类型定义为“原语类型由Java编程语言预定义并由其reserved关键字命名。” 更具描述性的定义是原始类型,它是Java编程语言中预定义的数据。 类型“ null”和“ void”不在原始类型中。

Null是默认引用值,或“ null类型具有一个值,null引用,由null文字null表示”。[Orac 2019] void类型指示非返回值方法,或“在方法声明和定义中使用若要指定该方法不返回任何类型,则该方法返回void。 它不是一种类型,并且没有C / C ++中的无效引用/指针。” [Wiki 2019b]

由于ZeptoN是Java,因此可以得出以下结论:基本类型完全相似。

5.2对象包装器类型

基本类型是有效的,但是Java中的一个“皱纹”不是对象。 没有引用原始类型,没有任何对象或状态。 但是对象类型有时是必要且有用的。 因此,Java提供了对象包装器类型来使原语对象化。

Eckel [Ecke 2003]将对象类型包装器描述为:“原始数据类型的“包装器”类允许您在堆上创建一个非原始对象来表示该原始类型。”

例如,要将原始类型与任何Java集合一起使用,则需要将原始类型作为对象类型。 Java具有自动将原始类型提升为对象类型包装器的功能。

5.3自动装箱性能

具有自动装箱的功能(因为ZeptoN中使用Java 5),但是更简单的方法是简单地将所有原始类型提升为对象。 Java在大多数原语之间使用自动装箱(null和void除外),但是在原语类型(例如,简单为datum)和包装类型Integer(作为对象)之间没有联系。

另一个重要的考虑因素是性能,对自动装箱的无限制使用和未考虑使用都可能导致Java字节码出现性能问题。 升级为对象的此功能的最大优点之一是编写的代码更少,源代码更干净。

无效和无效这两个原始类型不是基准,因此不会提升为对象。 布尔,字节,字符,双精度型,浮点型,整型,长型和短型这8种原始类型被提升为对象。 但是与原始类型相比,对象类型将使用更多的内存。

5.4用原始类型转译ZeptoN源

考虑以下简单的ZeptoN程序“ polyMathPrimitive1.zep”,该程序根据for循环(因此为多项式)中的索引来计算数字,但使用原始类型int进行计算。 静态方法“ polyMathLoop”用作从程序块调用的方法。

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);
}

使用整数常量1000调用polyMathLoop()方法。除了重复计算相同的多项式之外,该方法实际上不做任何事情。

使用ZeptoN编译器进行编译时,然后运行:

/Users/williamgilreath$java -cp . Zep polyMathPrimitive.zep
/Users/williamgilreath$java -cp . javacodegeeks.polyMathPrimitive1
Total time: 18484 nanosec

ZeptoN程序“ polyMathObject.zep”说明了等效的ZeptoN在编译时为:

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编译器进行编译时,然后运行:

/Users/williamgilreath$java -cp . ZepC polyMathObject.zep
/Users/williamgilreath$java -cp . javacodegeeks.polyMathObject
Total time: 512084 nanosec

两个性能时间的比率表明总比率为1:27.7。 显然,将每个原语完全升级为对象类型可能会对性能造成问题。

考虑一种替代方法,其中ZeptoN程序中并非每个整数都是原始int或对象包装Integer。 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编译器进行编译时,然后运行:

/Users/williamgilreath$java -cp . Zep polyMathPrimitive2.zep
/Users/williamgilreath$java -cp . javacodegeeks.polyMathPrimitive2 Total time: 92350 nanosec

表演时间的比例表明总体比例为1:5的差异。 与纯对象包装类型实现相比,这是性能上的改进。 混合方法的性能更高。

5.5“促销到对象”的功能语法

之前和之后的示例说明了从原始int到对象包装的转换Integer是全部或全部。 性能显然会受到极大影响。 但是,在某些情况下,开发人员想要指定原始类型仍然是原始类型,尤其是在性能指标上。 这反映了前述方法的特点,即为开发人员提供了基本类型或对象类型的选择。

语法是从原始类型升级为对象类型的一种排斥。 对于语法,没有任何其他指示符的普通原语被提升为对象类型。 因此,int变成Integer,double变成Double,依此类推。

排除语法是从JavaCC [ref]语法中“借用”的,用于表达语法规则,正如Copeland [Cope 2009]解释的那样,“……是吗? 量词,它与指定模式的零个或一次匹配。”

从提升为对象类型中排除的原始类型具有字符“?”的结尾“钩”或“问号”。 在标识符之后指示转编译器不要将原始类型提升为对象类型。 带有“?”字符 原始类型仍然是原始类型。 因此是“ int?” 被编译为“ int”而不是“ Integer”,因为没有提升对象类型。

重写原始类型和对象类型的原始混合语法,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程序。

该语法允许开发人员选择是将基元保留为基元类型,还是提升为对象类型包装器。 因此,开发人员处于控制之中,而不是ZeptoN反编译器。 语法有点熟悉,类似于JavaCC生产规则,Kotlin的语法用于允许的无效值,Swift的语法用于nil。 因此,尽管语义完全不同,但语法还是有些熟悉。

6.功能语法的Transpiler

指定原始类型的语法很简单,很熟悉,仍然保持原始。 问题是如何在反编译器中实现此功能,以便将ZeptoN反编译为Java源代码。 但是ZeptoN转编译器已经将ZeptoN源代码转换为Java源代码,然后使用Java Compiler API对其进行编译。

转换功能语法的软件实现面临两个挑战:

  1. 实现特征语法的转译
  2. 利用现有的ZeptoN转编译器

这是经典的软件开发工程师的任务-在现有的旧版软件中实现功能。 简而言之,创建一个新算法,然后在ZeptoN转编译器的旧版代码中实现。

6.1特征算法

从基本类型到对象类型的特征的算法很简单,与任何更复杂的编译相比,它更具有正则表达式的搜索和替换过程。

该算法分为三个步骤:

  1. 重命名原语以将原语保留为中间标识符
  2. 将原始类型重命名为对象类型包装器
  3. 将中间标识符重命名为原始类型

算法的每个步骤然后依次处理下一步中的字符串,直到将具有语法功能的原始ZeptoN源转换为具有原始类型和对象类型的ZeptoN源代码。

6.1.1将原语重命名为中间标识符

该算法的第一步是保留要保留的基本体。 但是重命名是必需的,以避免搜索并替换为对象包装器类型。 可以使用任何不同的替换,但是将原始字符的大写字母与字母'Q'串联在一起可以简化要编写的代码,因为每个原始标识符都可以在搜索中使用,并可以用正则表达式替换。

6.1.2重命名原语为对象类型包装器

中间步骤是在ZeptoN源代码中搜索原始类型标识符并将其替换为对象类型标识符。 检查并替换每个原始标识符。 因此,原语保持原语并在算法的最后一步中恢复。

6.1.3重命名中间标识符为原始类型

该算法的最后一步将还原已重命名的原始类型。 使用唯一的,不相同的标识符,将替换原始类型标识符而不会在末尾添加问号,并且在ZeptoN源代码中,指示为在语法中保持原始的原始语言也是如此。

6.2功能语法的实现

该算法可以在一系列原始类型上使用三个for循环来实现,甚至可以更简单地使用臭名昭著的“一个内衬”来实现,后者更像是使用一个for循环的流。 因此,使用原始类型来转换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 transpileCode

6.3转换然后导出到文件

在“ transpileCode()”方法将特征语法转换为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”文件中的新功能语法变为“ .orig”文件。 将源代码文件读入字符串,然后转换为ZeptoN源代码。 然后将ZeptoN源代码文件写入“ .zep”文件。 这将保留传递的原始文件参数以及任何命令行参数参数。 其余编译器使用现有的ZeptoN转编译器实现。

7.使用ZeptoN的转编译器实现

ZeptoN转编译器用作转编译器的旧版或预先存在的代码,以集成新功能语法。 方法是:

  1. 外部文件用于预处理转编译器的中间代码
  2. 现有的ZeptoN反编译器是后处理器反编译器和编译器

因此,具有ZeptoN中功能语法的新转编译器将使用外部文件,因此不会在内部进行编译。 这样做的好处是,在使用新语法对ZeptoN源代码进行预处理之后,可以将中间ZeptoN源代码存储为整个编译过程的一部分。

现有的ZeptoN反编译器(使用内存中的Java编译器将反编译的ZeptoN编译为Java源代码)用作包或库。 因此,现有的ZeptoN编译器不会被修改或细分,而是在编译的最后阶段使用。

7.1压缩现有的ZeptoN Transcompiler

现有的ZeptoN转编译器“ Zep.java”是在Github存储库中发布的开源Java。 转编译器在内部将文件“ source.zep”中的ZeptoN源代码转换为Java源代码,然后使用Java Compiler API内存将其编译为字节码.class文件。

Transcompiler Zep.java类的两个核心方法当然是“ main(String [] args)”作为调用的主要方法,以及“ compile(String [] args)”方法进行实际的反编译,然后编译为Java字节码.class文件。 问题是将原始类型转换为对象包装器类型后要调用哪种方法。 这两个方法是“ main()”方法或“ compile()”方法,它们都是静态的无状态方法。

7.1.1 main()方法

ZeptoN转编译器“ Zep.java”具有可以使用的“ main()”方法,因为所有参数均已保留,并且使用了外部文件。 “ 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”调用ZeptoN Transcompiler会遇到棘手的问题,因为成功或失败都会调用“ System.exit()”。 因此,不可能使用新的语法功能编译多个文件,因为编译的第一个文件将在成功或失败时终止。

7.1.2 compile()方法

ZeptoN转编译器方法“ compile()”由“ main()”方法调用。 该方法创建ZeptoN编译器的实例,处理命令行参数,并配置命令行参数。 如果没有传递参数,或没有文件提供给转编译器,则会引发错误。

ZeptoN转编译器的“ 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

实际的ZeptoN转编译器使用“ transpile()”方法返回Java源文件对象,该对象将传递给编译器实例方法“ compileZeptoN()”以生成Java字节码.class文件。 “ transpile()”方法将外部ZeptoN源文件读取为String对象,并转换为Java源代码,然后对其进行编译。

7.1.3调用compile()方法

“ compile()”方法用于将已转换的功能语法编译为字节码.class文件。 由于使用了外部文件,因此可能有两个错误:

  1. 文件错误是不可能的,因为由原语到对象的反编译方法创建了外部文件。
  2. 零参数是不可能的,因为反编译方法会创建ZeptoN源文件。
private static void compile(String[] args) { String[] fileList = getFileList(args);for(String fileName : fileList) { //rename, transpile fileList arguments}//end forZep.compile(args); }//end transpile

重命名文件,然后将新语法功能转换为ZeptoN源代码后,将调用ZeptoN转编译器“ compile()”,然后ZeptoN转编译器将完成转码为Java字节码.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扩展功能语法转译器摘要

将新语法功能转换为Java字节码.class文件的整个过程使用外部文件,因此大部分过程是重命名,删除,读取和写入源代码文件。 但是所有这些数据移动都允许使用带有编译器参数和文件名的“ compile()”来调用现有的ZeptoN转编译器。 整个过程是:

  1. 将新功能语法文件从“ .zep”重命名为“ .orig”
  2. 将“ .orig”读入String,然后以String的形式编译为ZeptoN源代码。
  3. 将字符串写入文件名“ .zep”
  4. 使用外部文件,参数调用现有的ZeptoN转编译器“ compile()”方法
  5. 删除中间的“ .zep”文件
  6. 将“ .orig”文件重命名为“ .zep”

7.2测试新的语法功能

新语法功能的实现已完成,但是现在可以测试ZeptoN编程语言中添加的新功能。

测试新的语法功能将使用四个ZeptoN源文件。 使用原始的ZeptoN编译器,该测试很简单: 以及改良的ZeptoN编译器:ZepPTO。 测试中使用的ZeptoN源代码文件是:

  1. polyMathPrimitive1.zep:所有类型都是基元
  2. polyMathPrimitive2.zep:混合类型是基元和对象类型
  3. polyMathObject.zep:所有类型都是对象类型
  4. polyMathSyntax.zep:类型正在使用新功能语法

Zep原始的ZeptoN源代码编译器将编译所有ZeptoN源文件,但包含新功能语法的'polyMathSyntax.zep'除外。 ZepPTO扩展的特色语法编译器将编译所有文件。

由于除“ polyMathSyntax.zep”以外的所有文件都将编译,否则该文件将因Zep反编译器而失败,但因ZepPTO反编译器而成功,因此使用此文件的输出进行比较,以避免不必要的重复和解释。

7.2.1使用ZeptoN编译新语法

当使用ZeptoN转编译器进行编译时,结果为:

图1:ZeptoN编译器错误

有11个错误,主要与新语法有关,不足为奇,因为现有的ZeptoN转编译器尚未实现新语法功能。

7.2.2使用ZepPTO的转编译器

使用新的ZepPTO(提升为对象)转编译器进行编译时,结果为:

/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.

现在运行生成的Java字节码.class文件,结果是:

/Users/williamgilreath$java -cp . javacodegeeks.polyMathSyntax Total time: 301515 nanosec

将ZeptoN源代码转换为字节码.class文件可使用Java运行时运行。

7.2.3使用Zep编译其他文件

其他具有常规ZeptoN语法的ZeptoN源文件是使用未扩展的ZeptoN转编译器“ Zep”和参数“ -echo”来编译的,以回显所使用的Javac参数以及编译器的整体成功或失败。

/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.

常规的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.

常规的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.

常规的ZeptoN编译器已成功编译ZeptoN源文件“ polyMathPrimitive2.zep”。

7.2.4使用ZepPTO编译其他文件

其他具有常规ZeptoN语法的ZeptoN源文件将通过扩展的ZeptoN转编译器“ ZepPTO”与参数“ -echo”一起进行编译,以回显所使用的Javac参数以及编译器的整体成败。

/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.

扩展的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.

扩展的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.

扩展的ZeptoN编译器已成功编译ZeptoN源文件“ polyMathPrimitive2.zep”。

7.2.5测试总结

通过两个转编译器对常规ZeptoN源文件和扩展语法功能的测试表明,扩展转编译器ZepPTO可编译为Java字节码.class文件。 新功能语法可将基本类型提升为对象类型包装程序,并使用新功能语法排除基本类型以保持基本类型。

8.结论

ZeptoN编程语言是Java,仅关注程序实体,这是Java编程语言所缺乏的功能。 这将创建一种与Java语法相似且兼容的编程语言。 这样的编程语言可以轻松地反编译为Java源代码,然后使用Java Compiler API编译为字节码.class文件。

ZeptoN编程语言通过添加具有新语法的新功能进行了扩展。 此功能是将原始类型(不包括null和void)转换为对象包装器类型。 这是编程语言的一个常见主题,通常在极端情况下被称为“蠕动性胎炎”或“特征蠕变”。 但是,对于编程语言语法中的新功能,必须对其进行设计和实现。

新功能语法是通过使用将新功能语法的ZeptoN源代码转换为普通ZeptoN源代码的转编译器来实现的。 使用现有的ZeptoN反编译器将源代码反编译为Java字节码。 这具有将现有的Transcompiler用于ZeptoN的优点,但是可以通过新功能自定义和扩展语言。 这样可以避免对ZeptoN中添加的新语法功能进行全新的实现

因此,重点是实现针对新语法功能的编译器,然后实施,利用现有的编译器和编译器,因为ZeptoN编译器先编译为Java源代码,然后再编译为Java字节码.class文件。 可以使用相同的方法来通过新功能扩展Java,使用WEJAC编译器[Gilr 2019b]将转编译后的Java源代码编译为纯Java源代码,然后编译为字节码.class文件。

9.参考

[Alpe 2000] Alpert,ShermanR。“原始类型被认为有害”。

英国文化协会,《 更多的Java宝石》 ,剑桥大学出版社,纽约,纽约,2000年,第435-454页。[英国2019年]。

“认知超载”,2015年5月20日, https://www.teachingenglish.org.uk/article/cognitive-overload 。

于2019年11月9日访问。[Cope 2009] Tom Copeland。

用JavaCC生成解析器 ,《百年纪念书》,弗吉尼亚州亚历山大市,2009年,第29页。[Ecke 2003] Eckel,Bruce。

《用Java思考》 ,Prentice-Hall,上萨德尔河,新泽西州,2003年,第3页。

90 [Gilr 2019a] Gilreath,William F.GitHub存储库“ WEJAC:Will's Elided Java API编译器,'' https ://wgilreath.github.io/WEJAC/.2019年12月31日访问。[Gilr2019b] Gilreath,William F.GitHub存储库“ 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语言规范,第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

ZeptoN正在将程序放入Java相关推荐

  1. 微信小程序--放入个性化手绘地图具体步骤(腾讯地图)

    微信小程序–放入个性化手绘地图具体步骤(腾讯地图) 前言:小程序中想要实现个性化手绘地图需要通过H5嵌入的模式进行实现. 1.首先需要一个腾讯地图的账号(微信登录即可),然后选择个性化地图进入(htt ...

  2. C语言如果实现电脑与plc通讯,PLC怎么连接电脑?怎么把在电脑编程好的程序放入PLC运行?...

    PLC怎么连接电脑,首先需要一根编程电缆线连接PLC和我们的电脑,连接线的种类不同所需要安装的驱动就不一样,安装驱动有时候会在安装编程软件的时候询问是否安装相对应的驱动,如果选择否,则需要在后期手动进 ...

  3. 使用 Electron 将应用程序放入托盘

    使用 Electron 将应用程序放入托盘 此系列文章的应用示例已发布于 GitHub: electron-api-demos-Zh_CN. 可以 Clone 或下载后运行查看. 欢迎 Star . ...

  4. java 简单 语言_将简单的表达式语言放入java中

    使用 JavaScript engine that is bundled with Java 1.6怎么样? 您可以看到如何传递所有参数: ScriptEngineManager manager = ...

  5. 安卓9 怎么运行老程序_PLC怎么连接电脑?怎么把在电脑编程好的程序放入PLC运行?...

    点击上方蓝字关注, 回复数字"100"领取电工经典电路图100例 今天给大家介绍三菱FX系列PLC如何接线和如何通过RS232进行下载程序,简单的说明帮助大家能快速与PLC通讯,并 ...

  6. java语言编写简易表达式_将简单的表达语言放入Java

    小编典典 您可以看到如何传递所有参数: ScriptEngineManager manager = new ScriptEngineManager(); ScriptEngine engine = m ...

  7. C/C++信息隐写术(四)之大程序藏入BMP文件

    在阅读这篇文章时请先阅读第三篇,第三篇链接如下: http://blog.csdn.net/qq78442761/article/details/54893792 这一节里面我们要做的是 把一个exe ...

  8. 沙盘:把危险程序放进沙盘运行 ,倒沙后无任何痕迹!

    沙盘:把危险程序放进沙盘运行 ,倒沙后无任何痕迹! 传统的杀毒软件依靠病毒库查杀,但病毒的更新永远是先于杀软,致使新病毒很难在第一时间被发现,众多同学装了360不用外挂账号依旧遭殃,这就是原因所在.( ...

  9. java sessionid放入cookie_sessionID和cookie

    一.cookie机制和session机制的区别 **************************************************************************** ...

最新文章

  1. CMAKE支持c++11的两种方式
  2. html 列表bootstrap,bootstrap都有哪些类?
  3. 对付惰性必杀:(10+2)*5法
  4. java中静态代码块的用法 static用法详解(转)
  5. Eratosthenes筛选求质数
  6. C++map的基本操作和使用
  7. prometheus+node_exporter+grafana实践
  8. Python中Pyaudio安装失败的解决办法
  9. Git使用教程:最详细、最傻瓜、最浅显、真正手把手教
  10. r语言 柱状图加星号_R语言绘制带有显著性字母标记的柱状图
  11. 翻译:如何理解梯度下降算法Gradient Descent algorithm
  12. 2022最新酷盒iApp源码V7.8版+内置超多功能
  13. 英语六级高频词汇速记 + 2018-6-2听力 Day02
  14. java 判断时间24小时_Java 判断时间是否超过24小时
  15. 2021-06-07 致即将毕业的你们
  16. IPA第八届少儿模特明星盛典 福州赛区 初赛圆满收官
  17. 微信小程序音频的使用:wx.createInnerAudioContext的使用
  18. 解决手机端中文输入法中keyup不灵便的方法
  19. K-Means对红酒数据进行聚类||python
  20. 【报告分享】2020年高科技互联网行业人才趋势与关键岗位薪酬报告.pdf(附下载链接)...

热门文章

  1. 欢乐纪中某A组赛【2019.7.10】
  2. P2375-[NOI2014]动物园【KMP,字符串】
  3. 牛客练习赛 63 F-牛牛的树行棋
  4. GYM 101669F - Binary Transformations
  5. 汇编语言(二十)之分类统计字符个数
  6. vue 动态修改路由参数
  7. 避免代码冗余,使用接口和泛型重构Java代码
  8. mysq和mysqli关系
  9. publiccms中将推荐页的内容显示在页面片段中
  10. 小二,先来两桂花豆沙包!