arm64のcompiler実装

source

print("hello world")

compiler.js

var {exec, write, show, error} = require("./utils.js");
var lexer = require("./lexer.js");
var parser = require("./parser-comp.js");
var genasm = require("./genasm.js");

var source = read("source.3");

var tokens = lexer(source);

show("処理前tokens =", tokens);

parser(tokens);

console.log("-------------");

exec("as source.s -o source.o");

exec("ld -lc --dynamic-linker /lib64/ld-linux-x86-64.so.2 -o exec source.o");

console.log(exec("./exec"));

parser-comp.js

module.exports = parser;
var {write,expect,accept,show,error} = require("./utils.js");
var tokens;

function parser(t) {
    tokens = t;
    return callprint();
}

function callprint(){
    if(tokens.length==0) return;

    expect(tokens,"print");

    expect(tokens,"(");

    var msg = tokens.shift();
    var codes = [];

    codes.push(".text");
    codes.push(".global _start");
    codes.push("_start:");

    codes.push("mov     x2,  #13");
    codes.push("adr     x1,  msg");

    codes.push("mov     x0,  #1 ");
    codes.push("mov     x8,  #64");

    codes.push("svc     #0");
    codes.push("mov     x0,  xzr");
    codes.push("mov     x8,  #93");
    codes.push("svc     #0 ");
    codes.push("msg:");
    codes.push(".asciz " + msg);
    codes.push("\n");

    var asm = codes.join("\n")+"\n";

    write("source.s",asm);

    expect(tokens,")");
}

utils.js

module.exports = {exec, write, read, show, error, accept, expect}

function exec(cmd) {
    return require('child_process').execSync(cmd, {encoding:"utf8"});
}

function write(filename, data){
    require('fs').writeFileSync(filename,data);
}

parser-comp.jsのcallfunctionでarm64用のassemblyを書いて保存する。
assemblerの実行は別に分ける。
interpreterの方はrun.jsで実行していたが、アセンブリの作成が入ってくるのね。