AWS LambdaのCustom Runtimesを利用してPascalのコードを実行してみる #reinvent

AWS Lambda Custom Runtimes芸人 Advent Calendar 2018の14日目の記事です。 今回はPascalでAWS Lambda Functionを実装してみます。
2018.12.14

こんにちは。shoitoです。

AWS Lambda Custom Runtimes芸人 Advent Calendar 2018の14日目の記事です。

re:Invent 2018で発表があったAWS Lambda Custom Runtimesのおかげで、AWS Lambdaでプログラミング言語で悩む必要はなくなりましたね。

New for AWS Lambda – Use Any Programming Language and Share Common Components | AWS News Blog

今回はPascalでAWS Lambda Functionを実装してみます。

そもそもPascalって?

Pascalというプログラミング言語はご存知でしょうか?

https://ja.wikipedia.org/wiki/Pascal

Pascal(パスカル)は、1970年に発表された言語。
ニクラウス・ヴィルトにより構造化プログラミングとして設計・デザインされた。
名称は、ブレーズ・パスカルにちなむ。

ALGOL、ALGOL Wをベースとし、簡素だがよく整った言語仕様(構文と意味)を持つ。
プログラミング教育を意識しており、「判読性」を重視している反面、「最適化」を犠牲にしていると批判もされた。
言語的には、自身のコンパイラを自身で書けるといった、言語処理系のブートストラップを備え、
多くの#実用プログラム例を持っている。

Wikipediaにはこのように紹介されてますが 言語的には、自身のコンパイラを自身で書ける というのはGo(v1.5以降)を想起させますね。

あとはPascalといえば、元BorlandのTurbo PascalDelphiを思い出される方も多いかもしれません。
※現在、Delphiはエンバガデロ社の製品となっています。

AWS Lambdaで動かすPascalのコード

今回、試してみるコードは The Hello World Collection のPascalコードを使います。

http://helloworldcollection.de/#Pascal

{Hello World in Pascal}

program HelloWorld(output);
begin
  WriteLn('Hello World!');
end.

上記コードを hello.pas としてファイルに保存します。

bootstrap ファイルはサンプルのシェルスクリプトを流用します。

#!/bin/sh

set -euo pipefail

EXEC="$LAMBDA_TASK_ROOT/$_HANDLER"

# Processing
while true
do
  HEADERS="$(mktemp)"
  # Get an event
  EVENT_DATA=$(curl -sS -LD "$HEADERS" -X GET "http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/next")
  REQUEST_ID=$(grep -Fi Lambda-Runtime-Aws-Request-Id "$HEADERS" | tr -d '[:space:]' | cut -d: -f2)

  # Execute the handler function from the script
  RESPONSE=$(echo "$EVENT_DATA" | $EXEC)

  # Send the response
  curl -X POST "http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/$REQUEST_ID/response"  -d "$RESPONSE"
done

ビルド

Pascalコードのコンパイル用のDockerコンテナイメージを作ります。
このDockerfileの定義では、Amazon LinuxにFree Pascalコンパイラをインストールしています。

FROM amazonlinux:2

RUN yum update -y && yum install -y gcc
RUN rpm -ivh https://downloads.sourceforge.net/project/freepascal/Linux/3.0.4/fpc-3.0.4-1.x86_64.rpm
$ docker build -t lambda/pascal .

コンパイル用のDockerコンテナイメージができあがったので、カレントディレクトリにある hello.pas をコンパイルします。

$ docker run --rm -v "$PWD":/tmp -it lambda/pascal fpc /tmp/hello.pas
$ ls
Dockerfile  bootstrap   hello       hello.o     hello.pas

実行

fpcでコンパイルして生成されたバイナリのhelloファイルとbootstrapファイルをzipファイルにアーカイブし、AWS LambdaのManagement Consoleからアップロードします。

$ zip -r lambda.zip bootstrap hello

あとはテストで実行してみると、無事にHello World!が表示されました。

さいごに

Pascalで実装したコードをAWS Lambdaで実行してみました。
bootstrapをシェルスクリプトで実装して、Pascalのコンパイル済みバイナリを呼び出す形にしてますが、そこもPascalで実装したいですね。