# 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-.";
  @silent    ??= false;
}

end {
  if (!@silent) {
  	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;
      str c = get_point_plot(cr, ci, @maxits);
      if (!@silent) {
			  printn c
      }
		}
    if (!@silent) {
		  print;
    }
	}
}

func get_point_plot(cr, ci, maxits): str {
	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);
	}
}
