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

}

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

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