手拉手教你实现一门编程语言 Enkel, 系列 16

本文系 Creating JVM language 翻译的第 16 篇。
原文中的代码和原文有不一致的地方均在新的代码仓库中更正过,建议参考新的代码仓库。

源码

Github

OOP 和 statics

面向对象语言中最大的优点是啥?我个人认为是多态, 如何实现多态,使用继承呗,可以在静态语义下使用继承么?肯定不行呀。

在我认为,静态语义违反了面向对象的思想,不应该出现在面向对象中,为了避免使用多态,你可以用单例呀。

因此,为何有 static 情况下,Java 还声称自己是面向对象的呢?我认为,Java 是为了迎合 C++ 更加方便的接纳 Java 才引入的历史因素。

去掉 static

直到上一篇博客,Enkel 中一直存在 static。包括 main 方法和其他的静态方法,这么是为了方便实现语言的其他特性,比如变量,条件表达式,循环,方法调用,然后才转成 OO。

那么我们来实现没有静态的 OO 吧。

main 方法

static main 方法需要 Java 程序员手动编写。Enkel 是这样处理的:

  • 编译器自动生成
  • 在 main 方法中,用默认的构造器创建一个对象
  • 然后调用 start 方法
  • 程序员需要提供 start 方法定义
private Function getGeneratedMainMethod() {
     FunctionParameter args = new FunctionParameter("args", BultInType.STRING_ARR, Optional.empty());
     FunctionSignature functionSignature = new FunctionSignature("main", Collections.singletonList(args), BultInType.VOID);
     ConstructorCall constructorCall = new ConstructorCall(scope.getClassName());
     FunctionSignature startFunSignature = new FunctionSignature("start", Collections.emptyList(), BultInType.VOID);
     FunctionCall startFunctionCall = new FunctionCall(startFunSignature, Collections.emptyList(), scope.getClassType());
     Block block = new Block(new Scope(scope), Arrays.asList(constructorCall,startFunctionCall));
     return new Function(functionSignature, block);
 }

start 方法是非静态的,但其实是 main 方法的一种变体。

INVOSTATIC vs INVOKEVIRTUAL

在第七部分,我用了 INVOKESTATIC 来做方法调用,是时候换成 INVOKEVIRTUAL 了。

INVOKEVIRTUAL 有一点和 INVOKESTATIC 有很大的差异,INVOKEVIRTUAL 需要一个所有者,INVOKESTATIC 从栈中出栈参数,INVOKEVIRTUAL 首先是把所有者出栈,然后才是出栈参数。

如果没有显示的提供所有者信息,默认用 this。


//Mapping antlr generated FunctionCallContext to FunctionCall 
@Override
public Expression visitFunctionCall(@NotNull EnkelParser.FunctionCallContext ctx) {
    //other stuff
    boolean ownerIsExplicit = ctx.owner != null;
    if(ownerIsExplicit) {
        Expression owner = ctx.owner.accept(this);
        return new FunctionCall(signature, arguments, owner);
    }
    ClassType thisType = new ClassType(scope.getClassName());
    return new FunctionCall(signature, arguments, new VarReference("this",thisType)); //pass "this" as a owner 
}
//Generating bytecode using mapped FunctionCall object
public void generate(FunctionCall functionCall) {
    functionCall.getOwner().accept(this); //generate owner (pushses it onto stack)
    generateArguments(functionCall);  //generate arguments
    String functionName = functionCall.getIdentifier();
    String methodDescriptor = DescriptorFactory.getMethodDescriptor(functionCall.getSignature());
    String ownerDescriptor = functionCall.getOwnerType().getInternalName();
    //Consumes owner and arguments off the stack
    methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, ownerDescriptor, functionName, methodDescriptor, false); 
}

示例

如下 Enkel 代码:

HelloStart {

    start {
        print "Hey I am non-static 'start' method"
    }
}

生成字节码:

public class HelloStart {
  public void start();
    Code:
       0: getstatic     #12                 // Field java/lang/System.out:Ljava/io/PrintStream;
       3: ldc           #14                 // String Hey I am non-static  'start' method
       5: invokevirtual #19                 // Method "Ljava/io/PrintStream;".println:(Ljava/lang/String;)V
       8: return

  //Constructor
  public HelloStart();
    Code:
       0: aload_0   //get "this"
       1: invokespecial #22                 // Method java/lang/Object."<init>":()V - call super
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: new           #2                  // class HelloStart - create new object
       3: dup       //duplicate new object so that invokespecial does not consumes it
       4: invokespecial #25                 // Method "<init>":()V - call constructor
       7: invokevirtual #27                 // Method start:()V
      10: return
}

与之对应 Java 类如下:

public class HelloStart {
    public HelloStart() {
    }

    public static void main(String[] var0) {
        (new HelloStart()).start();
    }
    
    public void start() {
        System.out.println("Hey I am non-static \'start\' method");
    }

}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,902评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,037评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,978评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,867评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,763评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,104评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,565评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,236评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,379评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,313评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,363评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,034评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,637评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,719评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,952评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,371评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,948评论 2 341

推荐阅读更多精彩内容

  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,537评论 18 399
  • 第6章类文件结构 6.1 概述 6.2 无关性基石 6.3 Class类文件的结构 java虚拟机不和包括java...
    kennethan阅读 905评论 0 2
  • 成长就像是一片郁葱的森林。里面有让人喜爱的草林;有让人恐惧的凶猛怪兽;也有迷惑我们的樱树花。一旦进入这座森林,就会...
    凉字拖阅读 127评论 0 0
  • 你以为你有很多路可以选择,但是在你周围有很多看不见的墙。 ——今何在 山桃熟了几次,海...
    y居合细雪阅读 235评论 0 2
  • 1893年12月28日 新中国第一任大法官张志让诞辰 1895年12月28日 世界第一部电影诞生 1903年12月...
    逸香居主白龍阅读 251评论 0 0