# Mandelbrot set generator: simple example of Miller DSL as programming language.
begin {
	# Set defaults
	@rcorn     = -2.0;
	@icorn     = -2.0;
	@side      = 4.0;
	@iheight   = 50;
	@iwidth    = 100;
	@maxits    = 100;
	@levelstep = 5;
	@chars     = "@X*o-.";
	@verbose   = false;

}

# Override defaults
@rcorn     = $rcorn;
@icorn     = $icorn;
@side      = $side;
@iheight   = $iheight;
@iwidth    = $iwidth;
@maxits    = $maxits;
@levelstep = $levelstep;
@chars     = $chars;
@verbose   = $verbose;

end {
	if (@verbose) {
		print "RCORN     = ".@rcorn;
		print "ICORN     = ".@icorn;
		print "SIDE      = ".@side;
		print "IHEIGHT   = ".@iheight;
		print "IWIDTH    = ".@iwidth;
		print "MAXITS    = ".@maxits;
		print "LEVELSTEP = ".@levelstep;
		print "CHARS     = ".@chars;
	}

	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);
	}
}
