function(environment, options, context, asObject) {
				this.environment = environment;
				this.options = options || {};

				log('debug', this.environment.disassemble() + "\n\n");

				this.name = this.environment.name;
				this.isChild = !!context;
				this.context = context || {
					programs: [],
					environments: [],
					aliases: { }
				};

				this.preamble();

				this.stackSlot = 0;
				this.stackVars = [];
				this.registers = { list: [] };
				this.hashes = [];
				this.compileStack = [];
				this.inlineStack = [];

				this.compileChildren(environment, options);

				var opcodes = environment.opcodes, opcode;

				this.i = 0;

				for(var l=opcodes.length; this.i<l; this.i++) {
					opcode = opcodes[this.i];

					if(opcode.opcode === 'DECLARE') {
						this[opcode.name] = opcode.value;
					} else {
						this[opcode.opcode].apply(this, opcode.args);
					}

					// Reset the stripNext flag if it was not set by this operation.
					if (opcode.opcode !== this.stripNext) {
						this.stripNext = false;
					}
				}

				// Flush any trailing content that might be pending.
				this.pushSource('');

				if (this.stackSlot || this.inlineStack.length || this.compileStack.length) {
					throw new Exception('Compile completed with content left on stack');
				}

				return this.createFunctionContext(asObject);
			}