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 { 

begin

  println("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,如果在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除外),但是在原语类型(例如int)和包装类型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 polyMathLoop

begin

  long 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 polyMathLoop

begin

  long 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 polyMathLoop

begin

  long 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 polyMathLoop

begin
  long? 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 end
    String prim = String.format("%s[?]", primitiveList[x]); 
    
    if(result.contains(primitiveList[x])){
      //primitive type to uppercase
      String upper = String.format("%SQ", primitiveList[x]);
      
      //exact match of primitive type
      String result = result 
                    . replaceAll(prim, upper)
                    . replaceAll(type, objectTypeList[x]) 
                    . replaceAll(upper, primitiveList[x]);
    }//end if

  }//end for

  return 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”文件。 源代码文件被读取为String,然后转换为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 if
    Zep.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 try
  System.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 if

  final Zep comp = new Zep();
  comp.processCommandLineArgs(args);
  if (files.isEmpty()) { 
    error(ERROR_NO_FILES);
  }//end if
  comp.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 for
  Zep.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 try

    String 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字节码。 这具有使用ZeptoN的现有转编译器的优势,但可以通过新功能自定义和扩展语言。 这避免了为ZeptoN中添加的新语法功能实现全新的实现

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

9.参考

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

[ More Java Gems] ,剑桥大学出版社,纽约,纽约,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年,第1页。

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值