Embedding the Crystal Compiler in Your Program



This content originally appeared on DEV Community and was authored by kojix2

Introduction

The Crystal compiler can be used as a library.
This document explains how to set it up and use it.

Creating the Project

First, create a new Crystal project.

crystal init app duck_egg
cd duck_egg

Editing shard.yml

Edit the shard.yml file as follows.
In this example, we add markd and reply to the dependencies section.

name: duck_egg
version: 0.1.0

targets:
  🥚:
    main: src/duck_egg.cr

dependencies:
  markd:
    github: icyleaf/markd
  reply:
    github: I3oris/reply

Creating duck_egg.cr

Create src/duck_egg.cr and add the following code.

require "compiler/requires"

BIRDS = [
  { "🐔", "cluck!" },
  { "🐓", "cock-a-doodle-doo" },
  { "🦃", "gobble" },
  { "🦆", "quack" },
  { "🦉", "hoot" },
  { "🦜", "squawk" },
  { "🕊", "coo" },
  { "🦢", "honk" },
  { "🦩", "brrrrt" },
  { "🐧", "honk honk" },
  { "🦤", "boop" },
  { "🦕", "Bwooooon!!" },
  { "🦖", "Raaaaawr!!" }
]

bird, sound = BIRDS.sample

compiler = Crystal::Compiler.new
source = Crystal::Compiler::Source.new(bird, %Q(puts "#{bird}  < #{sound}"))
compiler.compile source, bird

In this program, the Crystal compiler is embedded in the target 🥚.
When 🥚 is executed, a random bird is selected.
The embedded compiler generates a binary that displays the bird and its sound.

Building and Running

First, build the program.

shards build

Next, check the CRYSTAL_PATH environment variable to find the location of the Crystal standard library.

crystal env

The Crystal compiler requires the standard library even for very simple code such as puts 0.
Therefore, CRYSTAL_PATH must be set to include the path to the standard library.

export CRYSTAL_PATH=lib:/usr/local/bin/../share/crystal/src

Run the program:

bin/🥚

Example output:

🦖

Run the generated binary:

./🦖

Output:

🦖  < Raaaaawr!!

Summary

By using the Crystal compiler as a library, you can generate and compile code dynamically. This technique can be applied in many interesting ways.


This content originally appeared on DEV Community and was authored by kojix2