小ネタ 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環境をダウンロードしてインストールした。