ZeptoN正在将程序放入Java

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转编译器进行编译时,结果为:

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/340002.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Quarkus入门

Quarkus – 一个为OpenJDK HotSpot和GraalVM量身定制的Kubernetes本机Java堆栈&#xff0c;它是从最佳Java库和标准中精制而成的。 –是一个容器优先的框架&#xff0c;针对快速启动时间和低内存消耗进行了优化。 该框架基于许多流行的Java库构建&#xff0c;并且为构建标准RES…

vmware6.5.2序列号_教你如何查询苹果序列号,查询是否为官换机、激活时间等

如何查询你刚买的苹果设备是否为官换机&#xff1f;或想知道它的激活日期&#xff1f;保修时间&#xff1f;那么赶紧收藏本篇教程吧&#xff01;众所周知&#xff0c;在苹果官网查询苹果设备&#xff0c;是查询不到具体的信息&#xff08;比如激活日期、保修日期、是否为官换机…

linux 7启动文件夹在哪里设置密码,RHEL7 or CentOS7 的系统密码如何重置

导读RHEL7 的世界发生了变化&#xff0c;重置 root 密码的方式也一样。虽然中断引导过程的旧方法(init/bin/bash)仍然有效&#xff0c;但它不再是推荐的。“Systemd” 使用 “rd.break” 来中断引导。让我们快速浏览下整个过程。介绍目的在 RHEL7/CentOS7/Scientific Linux 7 中…

里氏替换原则_代码需要有单一职责,还要开闭,里氏替换又是什么鬼?

目录单一职责原则&#xff1a;开闭原则&#xff1a;里氏替换原则&#xff1a;单一职责原则&#xff1a;每一个系统中的功能都表示一个职责&#xff0c;这些职责可以映射到模块&#xff08;类&#xff09;中&#xff0c;且尽可能的保证这些类中没有功能上的重复&#xff0c;设计…

联想打印机7256显示更换墨盒_惠普打印机涉嫌垄断?只认自家“昂贵”墨盒,成本太高招架不住...

近日&#xff0c;有人爆料称&#xff0c;所在公司购买的惠普打印机使用原装墨盒时可正常打印&#xff0c;更换其他品牌墨盒后也不能正常使用&#xff0c;因此认为惠普公司有行业垄断的嫌疑。从细节来看&#xff0c;该公司购买了惠普同一型号但不同批次的两台打印机&#xff0c;…

linux mcelog 运行,服务器硬件检测(采用mcelog)

mt 内存监控&#xff1a;mcecheck.pyraid监控&#xff1a; check-raidmcelog 是 x86 的 Linux 系统上用来检查硬件错误&#xff0c;特别是内存和CPU错误的工具。安装方式yum install mcelog运行mcelog查看日志方式/var/log/mcelogMCE 0HARDWARE ERROR. This is NOT a software …

动手选择值

由于冠状病毒的存在&#xff0c;可选的东西在空中&#xff0c;一切都变得可选&#xff0c;例如可选的公共聚会&#xff0c;可选的在家工作&#xff0c;可选的旅行等。 我现在是时候谈论处理NULL引用的软件工程中真正的“ 可选 ”了。 托尼霍尔&#xff08;Tony Hoare&#xf…

wincc历史数据库_WinCC系统的基本功能介绍——自动化工程师必备

写在面前前面讲解了西门子的TIA Portal Wincc, Wincc Classic和Wincc OA (一文带你了解西门子Wincc),介绍了西门子的超大型/分布式SCADA系统Wincc OA(初识西门子Wincc OA——超大型/分布式SCADA)&#xff0c;还介绍了Wincc Classic的典型架构和选型指南(WinCC V7.5典型架构及选…

apache.camel_Apache Camel 2.14中的更多指标

apache.camelApache Camel 2.14将于本月晚些时候发布。 由于正在解决某些Apache基础结构问题&#xff0c;因此存在一些问题。 这篇博客文章讨论的是我们添加到此版本中的新功能之一。 感谢Lauri Kimmel捐赠了骆驼指标组件&#xff0c;我们将其与出色的Codehale指标库集成在一起…

依赖管理和Maven

Maven伟大而成熟。 几乎所有事物都总有解决方案。 您可能在组织项目上遇到的主要情况是依赖管理。 而不是每个项目都没有自己的依赖关系&#xff0c;您需要一种集中化的方式来继承那些依赖关系。 在这种情况下&#xff0c;您可以在父舞会上声明托管依赖项。 在我的示例中&…

linux ps 代码,Linux ps命令详解(示例代码)

ps命令是Process Status的缩写, 用来列出系统中当前运行的那些进程. ps命令列出的是当前那些进程的快照&#xff0c;就是执行ps命令的那个时刻的那些进程&#xff0c;如果想要动态的显示进程信息&#xff0c;就可以使用top命令ps常见命令参数********* simple selection ******…

Apache Kafka消费者再平衡

消费者重新平衡决定哪个消费者负责某些主题的所有可用分区的哪个子集。 例如&#xff0c;您可能有一个包含20个分区和10个使用者的主题。 在重新平衡结束时&#xff0c;您可能希望每个使用者都从2个分区中读取数据。 如果关闭了这些使用者中的10个&#xff0c;则可能会期望每个…

linux系统ll历史,Linux操作系统原理笔记

在Linux操作系统内核内部&#xff0c;进程是通过一个链表&#xff0c;而且是一个双向链表来管理的。进程描述符&#xff1a;每一个进程都有其描述符&#xff0c;每一个描述符彼此之间都有关联性的。双向链表&#xff1a;一个进程内部可能包含多个线程。上下文切换(Context swtc…

java工程师的终极书单_Java 9 –终极功能列表

java工程师的终极书单这篇文章将针对即将到来的Java 9版本进行更新&#xff0c;新增功能 &#xff08; 最新更新&#xff1a;2014年 9月9日 &#xff09; OpenJDK开发正在加快速度&#xff1a;2014年3月Java 8发布后&#xff0c;我们预计将进入2年的发布周期。 据报道&#xf…

称之为例外?

尽管这是一个与测试和Wiremock有关的Java示例&#xff0c;但它涉及一个更普遍的问题。 我们正在尝试重试Wiremock的verify方法&#xff0c;该方法可能会在我们要检查的端点被命中之前由测试调用。 在这种情况下&#xff0c;我们想在几秒钟后重试一次直到超时。 有趣的是&#…

c语言字符大于等于怎么打,c语言大于等于怎么打?

c语言大于等于怎么打&#xff1f;C语言‘大于等于符号是“>”&#xff1b;“>”是关系运算符用于比较运算。包括大于(>)、小于()、小于等于(<)和不等于(!)六种。注意要在英文的输入状态下写c代码。知识拓展&#xff1a;C语言运算符号指的是运算符号。C语言中的符号…

用c语言编写的源文件经过编译,若没有产生编译错误,则系统将,用 C 语言编写的源文件经过编译,若没有产生编译错误,则系统将(??)...

用C语言有产译错拖拉动工:旋是用一种耕机耕作机(件的机具智慧职教作部)驱。编写编译标准是消商品衡量和品价格价值质的直接费者。文件误则单反卡为相机用的最常存储。能给您提网球的(大力拍上量)是供最在击球时&#xff0c;的手的一使你舒服又能域感最个区。的是下列说法正确&a…

junit:junit_简而言之,JUnit:Hello World

junit:junit对于Java世界中的开发人员而言&#xff0c; JUnit似乎是最受欢迎的测试工具 。 因此&#xff0c;难怪就此主题已经写了一些好书 。 但是&#xff0c;通过以顾问为生&#xff0c;我仍然经常遇到程序员&#xff0c;他们至多对工具及其正确用法都不了解。 因此&#x…

android 多个复选框,Android UI控件之CheckBox(复选框、多选框)

上一篇文章中学习了RadioButton。知道了RadionButton的基本用法&#xff0c;实现起来也是听简单的和RadioButton一样CheckBox也是一个使用的非常多的控件&#xff0c;Android中它的的用法也挺简单的。以一个例子程序为例&#xff1a;同样先看一个常规的实现&#xff1a;布局文件…

android调用虚拟摄像头方法,Android:如何在模拟器中使用网络摄像头?

我通过在AVD Manager中将前置摄像头设置为“ webcam0”将摄像头连接到仿真器。 启动模拟器的相机应用程序时&#xff0c;出现错误CameraService::connect X (pid 702) rejected (invalid cameraId 0).这是Android源代码的相关部分&#xff1a;sp CameraService::connect(const …