# Mandelbrot set generator: simple example of Miller DSL as programming language.
begin {
	# Set defaults
	if (is_absent(@rcorn)) {
		@rcorn = -2.0;
	}
	if (is_absent(@icorn)) {
		@icorn = -2.0;
	}
	if (is_absent(@side)) {
		@side = 4.0;
	}
	if (is_absent(@iheight)) {
		@iheight =  500;
	}
	if (is_absent(@iwidth)) {
		@iwidth = 1000;
	}
	if (is_absent(@maxits)) {
		@maxits =  100;
	}
	if (is_absent(@levelstep)) {
		@levelstep =    5;
	}
	if (is_absent(@chars)) {
		@chars = "@X*o-.";
	}
	if (is_absent(@silent)) {
		@silent = false
	}
}

end {
	for (int ii = @iheight-1; ii >= 0; ii -= 1) {
		num ci = @icorn + (ii/@iheight) * @side;
		for (int ir = 0; ir < @iwidth; ir += 1) {
			num cr = @rcorn + (ir/@iwidth) * @side;
			printn get_point_plot(cr, ci, @maxits);
		}
		print;
	}
}

func get_point_plot(cr, ci, maxits) {
	num zr = 0.0;
	num zi = 0.0;

	int iti = 0;
	bool escaped = false;
	num zt = 0;
	for (iti = 0; iti < maxits; iti += 1) {
		num mag = zr*zr + zi+zi;
		if (mag > 4.0) {
				escaped = true;
				break;
		}
		# z := z^2 + c
		zt = zr*zr - zi*zi + cr;
		zi = 2*zr*zi + ci;
		zr = zt;
	}
	if (!escaped) {
		return ".";
	} else {
		int level = (iti // @levelstep) % strlen(@chars);
		return substr(@chars, level, level);
	}
}
