小ネタ 2013-004

Javaバイトコードを生成するTiny BASICコンパイラを作ってみた

昨年、CIL(MSIL)中間コードを生成するTiny BASICコンパイラというのを作ってみた。(2012-09-01)
それをベースにJavaバイトコードを生成するTiny BASICコンパイラを作ってみた。(2013-03-01)


1. つくってみたもの

 Tiny Basic Compiler (Javaバイトコード版)

 [ Tiny Basic Compiler 実行ファイル+ソースコード tinybas_java_01.zip (download) ]

 特徴
 ・整数型の小型なBASIC
 ・シンプルな言語仕様なのでソースコードも短く、コンパイラの仕組みを学習するサンプルとして活用できる


2. 使い方


 BASICのソースコードをコンパイルし、出力される.jファイルをJasminというJavaバイトコードアセンブラを使ってアセンブルして.classファイルを生成する。

 順番に手順を説明すると以下のとおり。

 サンプルのソースコードは例えば次のようになる。(example1.bas)
 10 INPUT X
 20 Y= x*x + 6*x + 9
 30 PRINT Y


 コマンドラインで、次のようにコマンド入力してコンパイルする。
 % tinybas example1.bas

 結果、example1.j が得られる。
 この.j ファイルはJasmin用のアセンブリーソースコードである。
 Jasminを使って.exeファイルを作る。
 % jasmin example1.j
 で、basic_program.classが作られる。

 実行するには、次のようにする。
 % java basic_program

 ちなみにアセンブリーソースコード(example1.jファイル)は、以下のように生成される。

;//============================================================
;//	Compiler: Tiny BasicCompiler (JavaVM) Ver 0.1
;//	Source: example1.bas
;//	Object: example1.j
;//============================================================

.class public basic_program
.super java/lang/Object
.method public <init>()V
	aload_0
	invokenonvirtual java/lang/Object/<init>()V
	return
.end method

.method public static main([Ljava/lang/String;)V
	.limit locals 1000
	.limit stack 16
	;//------------------------------------

_L10:
;	Variable 0
	ldc	"?"
	getstatic java/lang/System/out Ljava/io/PrintStream;
	swap
	invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V
	new java/io/InputStreamReader
	dup
	getstatic java/lang/System/in Ljava/io/InputStream;
	invokespecial java/io/InputStreamReader/<init>(Ljava/io/InputStream;)V
	new java/io/BufferedReader
	dup_x1
	swap
	invokespecial java/io/BufferedReader/<init>(Ljava/io/Reader;)V
	invokevirtual java/io/BufferedReader/readLine()Ljava/lang/String;
	invokestatic java/lang/Integer/parseInt(Ljava/lang/String;)I
	istore	0

_L20:
;	Variable 1
	iload	0
	iload	0
	imul
	sipush	6
	iload	0
	imul
	iadd
	sipush	9
	iadd
	istore	1

_L30:
	iload	1
	invokestatic java/lang/String/valueOf(I)Ljava/lang/String;
	getstatic java/lang/System/out Ljava/io/PrintStream;
	swap
	invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V

	;//------------------------------------
_END:
	return
.end method

Windows環境以外でも試してみる

 Mac OS X上で動かしてみた。
 XcodeからAppStore経由してgcc開発環境(実際はLLVM)をインストールし、OracleからMac OS X用のJava環境をダウンロードしてインストールした。