| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * $Id$ | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |     Copyright (c) 2014-2016 Chung, Hyung-Hwan. All rights reserved. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Redistribution and use in source and binary forms, with or without | 
					
						
							|  |  |  |     modification, are permitted provided that the following conditions | 
					
						
							|  |  |  |     are met: | 
					
						
							|  |  |  |     1. Redistributions of source code must retain the above copyright | 
					
						
							|  |  |  |        notice, this list of conditions and the following disclaimer. | 
					
						
							|  |  |  |     2. Redistributions in binary form must reproduce the above copyright | 
					
						
							|  |  |  |        notice, this list of conditions and the following disclaimer in the | 
					
						
							|  |  |  |        documentation and/or other materials provided with the distribution. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR | 
					
						
							|  |  |  |     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | 
					
						
							|  |  |  |     OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | 
					
						
							|  |  |  |     IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | 
					
						
							|  |  |  |     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | 
					
						
							|  |  |  |     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
					
						
							|  |  |  |     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
					
						
							|  |  |  |     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
					
						
							|  |  |  |     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 
					
						
							|  |  |  |     THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "hcl-prv.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | enum | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	VAR_NAMED, | 
					
						
							| 
									
										
										
										
											2016-10-01 04:36:48 +00:00
										 |  |  | 	VAR_INDEXED | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-04 17:56:28 +00:00
										 |  |  | #define CODE_BUFFER_ALIGN 1024 /* TODO: set a bigger value */
 | 
					
						
							| 
									
										
										
										
											2016-09-29 13:20:09 +00:00
										 |  |  | #define TV_BUFFER_ALIGN 256
 | 
					
						
							|  |  |  | #define BLK_TMPRCNT_BUFFER_ALIGN 128
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | #define EMIT_BYTE_INSTRUCTION(hcl,code) \
 | 
					
						
							|  |  |  | 	do { if (emit_byte_instruction(hcl,code) <= -1) return -1; } while(0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define EMIT_SINGLE_PARAM_INSTRUCTION(hcl,code) \
 | 
					
						
							|  |  |  | 	do { if (emit_byte_instruction(hcl,code) <= -1) return -1; } while(0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int add_literal (hcl_t* hcl, hcl_oop_t obj, hcl_oow_t* index) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	hcl_oow_t capa, i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* TODO: speed up the following duplicate check loop */ | 
					
						
							|  |  |  | 	for (i = 0; i < hcl->code.lit.len; i++) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		/* this removes redundancy of symbols, characters, and integers. */ | 
					
						
							|  |  |  | 		if (((hcl_oop_oop_t)hcl->code.lit.arr)->slot[i] == obj) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			*index = i; | 
					
						
							|  |  |  | 			return i; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	capa = HCL_OBJ_GET_SIZE(hcl->code.lit.arr); | 
					
						
							|  |  |  | 	if (hcl->code.lit.len >= capa) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		hcl_oop_t tmp; | 
					
						
							|  |  |  | 		hcl_oow_t newcapa; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		newcapa = capa + 20000; /* TODO: set a better resizing policy */ | 
					
						
							| 
									
										
										
										
											2016-10-06 17:49:47 +00:00
										 |  |  | 		tmp = hcl_remakengcarray (hcl, (hcl_oop_t)hcl->code.lit.arr, newcapa); | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 		if (!tmp) return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-06 17:49:47 +00:00
										 |  |  | 		hcl->code.lit.arr = (hcl_oop_oop_t)tmp; | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	*index = hcl->code.lit.len; | 
					
						
							|  |  |  | 	((hcl_oop_oop_t)hcl->code.lit.arr)->slot[hcl->code.lit.len++] = obj; | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-29 13:20:09 +00:00
										 |  |  | static int add_temporary_variable (hcl_t* hcl, hcl_oop_t name, hcl_oow_t dup_check_start) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	hcl_oow_t i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	HCL_ASSERT (HCL_IS_SYMBOL (hcl, name)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i = dup_check_start; i < hcl->c->tv.size; i++) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		HCL_ASSERT (HCL_IS_SYMBOL (hcl, hcl->c->tv.ptr[i])); | 
					
						
							|  |  |  | 		if (hcl->c->tv.ptr[i] == name) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			hcl->errnum = HCL_EEXIST; | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (hcl->c->tv.size >= hcl->c->tv.capa) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		hcl_oop_t* tmp; | 
					
						
							|  |  |  | 		hcl_oow_t newcapa; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		newcapa = HCL_ALIGN (hcl->c->tv.capa + 1, TV_BUFFER_ALIGN); /* TODO: set a better resizing policy */ | 
					
						
							|  |  |  | 		tmp = hcl_reallocmem (hcl, hcl->c->tv.ptr, newcapa); | 
					
						
							|  |  |  | 		if (!tmp) return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		hcl->c->tv.capa = newcapa; | 
					
						
							|  |  |  | 		hcl->c->tv.ptr = tmp; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	hcl->c->tv.ptr[hcl->c->tv.size++] = name; | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int find_temporary_variable_backward (hcl_t* hcl, hcl_oop_t name, hcl_oow_t* index) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	hcl_oow_t i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	HCL_ASSERT (HCL_IS_SYMBOL (hcl, name)); | 
					
						
							|  |  |  | 	for (i = hcl->c->tv.size; i > 0; ) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		--i; | 
					
						
							|  |  |  | 		HCL_ASSERT (HCL_IS_SYMBOL (hcl, hcl->c->tv.ptr[i])); | 
					
						
							|  |  |  | 		if (hcl->c->tv.ptr[i] == name) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			*index = i; | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	hcl->errnum = HCL_ENOENT; | 
					
						
							|  |  |  | 	return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int store_temporary_variable_count_for_block (hcl_t* hcl, hcl_oow_t tmpr_count) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	HCL_ASSERT (hcl->c->blk.depth >= 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (hcl->c->blk.depth >= hcl->c->blk.tmprcnt_capa) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		hcl_oow_t* tmp; | 
					
						
							|  |  |  | 		hcl_oow_t newcapa; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		newcapa = HCL_ALIGN (hcl->c->blk.depth + 1, BLK_TMPRCNT_BUFFER_ALIGN); | 
					
						
							|  |  |  | 		tmp = (hcl_oow_t*)hcl_reallocmem (hcl, hcl->c->blk.tmprcnt, newcapa * HCL_SIZEOF(*tmp)); | 
					
						
							|  |  |  | 		if (!tmp) return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		hcl->c->blk.tmprcnt_capa = newcapa; | 
					
						
							|  |  |  | 		hcl->c->blk.tmprcnt = tmp; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	hcl->c->blk.tmprcnt[hcl->c->blk.depth] = tmpr_count; | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ========================================================================= */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | static HCL_INLINE void patch_instruction (hcl_t* hcl, hcl_oow_t index, hcl_oob_t bc) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	HCL_ASSERT (index < hcl->code.bc.len); | 
					
						
							| 
									
										
										
										
											2016-10-04 17:56:28 +00:00
										 |  |  | 	hcl->code.bc.arr->slot[index] = bc; | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int emit_byte_instruction (hcl_t* hcl, hcl_oob_t bc) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	hcl_oow_t capa; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-04 17:56:28 +00:00
										 |  |  | 	/* the context object has the ip field. it should be representable
 | 
					
						
							|  |  |  | 	 * in a small integer. for simplicity, limit the total byte code length | 
					
						
							|  |  |  | 	 * to fit in a small integer. because 'ip' points to the next instruction | 
					
						
							|  |  |  | 	 * to execute, he upper bound should be (max - 1) so that i stays | 
					
						
							|  |  |  | 	 * at the max when incremented */ | 
					
						
							|  |  |  | 	if (hcl->code.bc.len == HCL_SMOOI_MAX - 1) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		hcl->errnum = HCL_EBCFULL; /* byte code full/too big */ | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 	capa = HCL_OBJ_GET_SIZE(hcl->code.bc.arr); | 
					
						
							|  |  |  | 	if (hcl->code.bc.len >= capa) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		hcl_oop_t tmp; | 
					
						
							|  |  |  | 		hcl_oow_t newcapa; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-04 17:56:28 +00:00
										 |  |  | 		newcapa = HCL_ALIGN (capa + 1, CODE_BUFFER_ALIGN); | 
					
						
							|  |  |  | 		tmp = hcl_remakengcbytearray (hcl, (hcl_oop_t)hcl->code.bc.arr, newcapa); | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 		if (!tmp) return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-04 17:56:28 +00:00
										 |  |  | 		hcl->code.bc.arr = (hcl_oop_byte_t)tmp; | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-04 17:56:28 +00:00
										 |  |  | 	hcl->code.bc.arr->slot[hcl->code.bc.len++] = bc; | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int emit_single_param_instruction (hcl_t* hcl, int cmd, hcl_oow_t param_1) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	hcl_oob_t bc; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	switch (cmd) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		case BCODE_PUSH_INSTVAR_0: | 
					
						
							|  |  |  | 		case BCODE_STORE_INTO_INSTVAR_0: | 
					
						
							|  |  |  | 		case BCODE_POP_INTO_INSTVAR_0: | 
					
						
							|  |  |  | 		case HCL_CODE_PUSH_TEMPVAR_0: | 
					
						
							| 
									
										
										
										
											2016-10-01 04:36:48 +00:00
										 |  |  | 		case HCL_CODE_STORE_INTO_TEMPVAR_0: | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 		case BCODE_POP_INTO_TEMPVAR_0: | 
					
						
							|  |  |  | 			if (param_1 < 8) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				/* low 3 bits to hold the parameter */ | 
					
						
							|  |  |  | 				bc = (hcl_oob_t)(cmd & 0xF8) | (hcl_oob_t)param_1; | 
					
						
							|  |  |  | 				goto write_short; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				/* convert the code to a long version */ | 
					
						
							|  |  |  | 				bc = cmd | 0x80; | 
					
						
							|  |  |  | 				goto write_long; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case HCL_CODE_PUSH_LITERAL_0: | 
					
						
							|  |  |  | 			if (param_1 < 8) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				/* low 3 bits to hold the parameter */ | 
					
						
							|  |  |  | 				bc = (hcl_oob_t)(cmd & 0xF8) | (hcl_oob_t)param_1; | 
					
						
							|  |  |  | 				goto write_short; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else if (param_1 <= MAX_CODE_PARAM) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				bc = HCL_CODE_PUSH_LITERAL_X; /* cmd | 0x80 */ | 
					
						
							|  |  |  | 				goto write_long; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				bc = HCL_CODE_PUSH_LITERAL_X2; /* HCL_CODE_PUSH_LITERAL_4 | 0x80 */ | 
					
						
							|  |  |  | 				goto write_long2; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case HCL_CODE_PUSH_OBJECT_0: | 
					
						
							|  |  |  | 		case HCL_CODE_STORE_INTO_OBJECT_0: | 
					
						
							| 
									
										
										
										
											2016-09-29 13:20:09 +00:00
										 |  |  | 		case BCODE_POP_INTO_OBJECT_0: | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 		case HCL_CODE_JUMP_FORWARD_0: | 
					
						
							|  |  |  | 		case HCL_CODE_JUMP_BACKWARD_0: | 
					
						
							| 
									
										
										
										
											2016-10-01 04:36:48 +00:00
										 |  |  | 		case BCODE_JUMP_IF_TRUE_0: | 
					
						
							|  |  |  | 		case BCODE_JUMP_IF_FALSE_0: | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 		case HCL_CODE_CALL_0: | 
					
						
							|  |  |  | 			if (param_1 < 4) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				/* low 2 bits to hold the parameter */ | 
					
						
							|  |  |  | 				bc = (hcl_oob_t)(cmd & 0xFC) | (hcl_oob_t)param_1; | 
					
						
							|  |  |  | 				goto write_short; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				/* convert the code to a long version */ | 
					
						
							|  |  |  | 				bc = cmd | 0x80; | 
					
						
							|  |  |  | 				goto write_long; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case HCL_CODE_JUMP2_FORWARD: | 
					
						
							|  |  |  | 		case HCL_CODE_JUMP2_BACKWARD: | 
					
						
							|  |  |  | 		case HCL_CODE_PUSH_INTLIT: | 
					
						
							|  |  |  | 		case HCL_CODE_PUSH_NEGINTLIT: | 
					
						
							|  |  |  | 		case HCL_CODE_PUSH_CHARLIT: | 
					
						
							|  |  |  | 			bc = cmd; | 
					
						
							|  |  |  | 			goto write_long; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	hcl->errnum = HCL_EINVAL; | 
					
						
							|  |  |  | 	return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | write_short: | 
					
						
							|  |  |  | 	if (emit_byte_instruction(hcl, bc) <= -1) return -1; | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | write_long: | 
					
						
							|  |  |  | 	if (param_1 > MAX_CODE_PARAM)  | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		hcl->errnum = HCL_ETOOBIG; | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #if (HCL_BCODE_LONG_PARAM_SIZE == 2)
 | 
					
						
							|  |  |  | 	if (emit_byte_instruction(hcl, bc) <= -1 || | 
					
						
							|  |  |  | 	    emit_byte_instruction(hcl, (param_1 >> 8) & 0xFF) <= -1 || | 
					
						
							|  |  |  | 	    emit_byte_instruction(hcl, param_1 & 0xFF) <= -1) return -1; | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 	if (emit_byte_instruction(hcl, bc) <= -1 || | 
					
						
							|  |  |  | 	    emit_byte_instruction(hcl, param_1) <= -1) return -1; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | write_long2: | 
					
						
							|  |  |  | 	if (param_1 > MAX_CODE_PARAM2)  | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		hcl->errnum = HCL_ETOOBIG; | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #if (HCL_BCODE_LONG_PARAM_SIZE == 2)
 | 
					
						
							|  |  |  | 	if (emit_byte_instruction(hcl, bc) <= -1 || | 
					
						
							|  |  |  | 	    emit_byte_instruction(hcl, (param_1 >> 24) & 0xFF) <= -1 || | 
					
						
							|  |  |  | 	    emit_byte_instruction(hcl, (param_1 >> 16) & 0xFF) <= -1 || | 
					
						
							|  |  |  | 	    emit_byte_instruction(hcl, (param_1 >>  8) & 0xFF) <= -1 || | 
					
						
							|  |  |  | 	    emit_byte_instruction(hcl, param_1 & 0xFF) <= -1) return -1; | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 	if (emit_byte_instruction(hcl, bc) <= -1 || | 
					
						
							|  |  |  | 	    emit_byte_instruction(hcl, (param_1 >> 8) & 0xFF) <= -1 || | 
					
						
							|  |  |  | 	    emit_byte_instruction(hcl, param_1 & 0xFF) <= -1) return -1; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int emit_double_param_instruction (hcl_t* hcl, int cmd, hcl_oow_t param_1, hcl_oow_t param_2) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	hcl_oob_t bc; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	switch (cmd) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2016-09-29 13:20:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 		case HCL_CODE_STORE_INTO_CTXTEMPVAR_0: | 
					
						
							| 
									
										
										
										
											2016-10-01 04:36:48 +00:00
										 |  |  | 		case BCODE_POP_INTO_CTXTEMPVAR_0: | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 		case HCL_CODE_PUSH_CTXTEMPVAR_0: | 
					
						
							| 
									
										
										
										
											2016-10-01 04:36:48 +00:00
										 |  |  | 		case BCODE_PUSH_OBJVAR_0: | 
					
						
							|  |  |  | 		case BCODE_STORE_INTO_OBJVAR_0: | 
					
						
							| 
									
										
										
										
											2016-09-29 13:20:09 +00:00
										 |  |  | 		case BCODE_POP_INTO_OBJVAR_0: | 
					
						
							| 
									
										
										
										
											2016-10-01 04:36:48 +00:00
										 |  |  | 		case BCODE_SEND_MESSAGE_0: | 
					
						
							|  |  |  | 		case BCODE_SEND_MESSAGE_TO_SUPER_0: | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 			if (param_1 < 4 && param_2 < 0xFF) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				/* low 2 bits of the instruction code is the first parameter */ | 
					
						
							|  |  |  | 				bc = (hcl_oob_t)(cmd & 0xFC) | (hcl_oob_t)param_1; | 
					
						
							|  |  |  | 				goto write_short; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				/* convert the code to a long version */ | 
					
						
							| 
									
										
										
										
											2016-09-29 13:20:09 +00:00
										 |  |  | 				bc = cmd | 0x80;  | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 				goto write_long; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2016-09-29 13:20:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		case HCL_CODE_MAKE_BLOCK: | 
					
						
							|  |  |  | 			bc = cmd; | 
					
						
							|  |  |  | 			goto write_long; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	hcl->errnum = HCL_EINVAL; | 
					
						
							|  |  |  | 	return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | write_short: | 
					
						
							|  |  |  | 	if (emit_byte_instruction(hcl, bc) <= -1 || | 
					
						
							|  |  |  | 	    emit_byte_instruction(hcl, param_2) <= -1) return -1; | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | write_long: | 
					
						
							|  |  |  | 	if (param_1 > MAX_CODE_PARAM || param_2 > MAX_CODE_PARAM) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		hcl->errnum = HCL_ETOOBIG; | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #if (HCL_BCODE_LONG_PARAM_SIZE == 2)
 | 
					
						
							|  |  |  | 	if (emit_byte_instruction(hcl, bc) <= -1 || | 
					
						
							|  |  |  | 	    emit_byte_instruction(hcl, param_1 >> 8) <= -1 || | 
					
						
							|  |  |  | 	    emit_byte_instruction(hcl, param_1 & 0xFF) <= -1 || | 
					
						
							|  |  |  | 	    emit_byte_instruction(hcl, param_2 >> 8) <= -1 || | 
					
						
							|  |  |  | 	    emit_byte_instruction(hcl, param_2 & 0xFF) <= -1) return -1; | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 	if (emit_byte_instruction(hcl, bc) <= -1 || | 
					
						
							|  |  |  | 	    emit_byte_instruction(hcl, param_1) <= -1 || | 
					
						
							|  |  |  | 	    emit_byte_instruction(hcl, param_2) <= -1) return -1; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  | write_long2: | 
					
						
							|  |  |  | 	if (param_1 > MAX_CODE_PARAM || param_2 > MAX_CODE_PARAM) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		hcl->errnum = HCL_ETOOBIG; | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #if (HCL_BCODE_LONG_PARAM_SIZE == 2)
 | 
					
						
							|  |  |  | 	if (emit_byte_instruction(hcl, bc) <= -1 || | 
					
						
							|  |  |  | 	    emit_byte_instruction(hcl, (param_1 >> 24) & 0xFF) <= -1 || | 
					
						
							|  |  |  | 	    emit_byte_instruction(hcl, (param_1 >> 16) & 0xFF) <= -1 || | 
					
						
							|  |  |  | 	    emit_byte_instruction(hcl, (param_1 >>  8) & 0xFF) <= -1 || | 
					
						
							|  |  |  | 	    emit_byte_instruction(hcl, param_1 & 0xFF) <= -1  || | 
					
						
							|  |  |  | 	    emit_byte_instruction(hcl, (param_2 >> 24) & 0xFF) <= -1 || | 
					
						
							|  |  |  | 	    emit_byte_instruction(hcl, (param_2 >> 16) & 0xFF) <= -1 || | 
					
						
							|  |  |  | 	    emit_byte_instruction(hcl, (param_2 >>  8) & 0xFF) <= -1 || | 
					
						
							|  |  |  | 	    emit_byte_instruction(hcl, param_2 & 0xFF) <= -1) return -1; | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 	if (emit_byte_instruction(hcl, bc) <= -1 || | 
					
						
							|  |  |  | 	    emit_byte_instruction(hcl, param_1 >> 8) <= -1 || | 
					
						
							|  |  |  | 	    emit_byte_instruction(hcl, param_1 & 0xFF) <= -1 || | 
					
						
							|  |  |  | 	    emit_byte_instruction(hcl, param_2 >> 8) <= -1 || | 
					
						
							|  |  |  | 	    emit_byte_instruction(hcl, param_2 & 0xFF) <= -1) return -1; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int emit_push_literal (hcl_t* hcl, hcl_oop_t obj) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	hcl_oow_t index; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (HCL_OOP_IS_SMOOI(obj)) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		hcl_ooi_t i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		i = HCL_OOP_TO_SMOOI(obj); | 
					
						
							|  |  |  | 		switch (i) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			case -1: | 
					
						
							|  |  |  | 				return emit_byte_instruction (hcl, HCL_CODE_PUSH_NEGONE); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			case 0: | 
					
						
							|  |  |  | 				return emit_byte_instruction (hcl, HCL_CODE_PUSH_ZERO); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			case 1: | 
					
						
							|  |  |  | 				return emit_byte_instruction (hcl, HCL_CODE_PUSH_ONE); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			case 2: | 
					
						
							|  |  |  | 				return emit_byte_instruction (hcl, HCL_CODE_PUSH_TWO); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (i >= 0 && i <= MAX_CODE_PARAM) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			return emit_single_param_instruction(hcl, HCL_CODE_PUSH_INTLIT, i); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else if (i < 0 && i >= -(hcl_ooi_t)MAX_CODE_PARAM) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			return emit_single_param_instruction(hcl, HCL_CODE_PUSH_NEGINTLIT, -i); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if (HCL_OOP_IS_CHAR(obj)) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		hcl_ooch_t i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		i = HCL_OOP_TO_CHAR(obj); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (i >= 0 && i <= MAX_CODE_PARAM) | 
					
						
							|  |  |  | 			return emit_single_param_instruction(hcl, HCL_CODE_PUSH_CHARLIT, i); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (add_literal(hcl, obj, &index) <= -1 || | 
					
						
							|  |  |  | 	    emit_single_param_instruction(hcl, HCL_CODE_PUSH_LITERAL_0, index) <= -1) return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ========================================================================= */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int push_cframe (hcl_t* hcl, int opcode, hcl_oop_t operand) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	hcl_cframe_t* tmp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (hcl->c->cfs.top == HCL_TYPE_MAX(hcl_ooi_t)) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		hcl->errnum = HCL_ETOOBIG; | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	hcl->c->cfs.top++; | 
					
						
							|  |  |  | 	HCL_ASSERT (hcl->c->cfs.top >= 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if ((hcl_oow_t)hcl->c->cfs.top >= hcl->c->cfs.capa) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		hcl_oow_t newcapa; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		newcapa = HCL_ALIGN (hcl->c->cfs.top + 256, 256); /* TODO: adjust this capacity */ | 
					
						
							|  |  |  | 		tmp = hcl_reallocmem (hcl, hcl->c->cfs.ptr, newcapa * HCL_SIZEOF(hcl_cframe_t)); | 
					
						
							|  |  |  | 		if (!tmp)  | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			hcl->c->cfs.top--; | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		hcl->c->cfs.capa = newcapa; | 
					
						
							|  |  |  | 		hcl->c->cfs.ptr = tmp; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	tmp = &hcl->c->cfs.ptr[hcl->c->cfs.top]; | 
					
						
							|  |  |  | 	tmp->opcode = opcode; | 
					
						
							|  |  |  | 	tmp->operand = operand; | 
					
						
							|  |  |  | 	/* leave tmp->u untouched/uninitialized */ | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static HCL_INLINE void pop_cframe (hcl_t* hcl) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	HCL_ASSERT (hcl->c->cfs.top >= 0); | 
					
						
							|  |  |  | 	hcl->c->cfs.top--; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define PUSH_CFRAME(hcl,opcode,operand) \
 | 
					
						
							|  |  |  | 	do { if (push_cframe(hcl,opcode,operand) <= -1) return -1; } while(0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define POP_CFRAME(hcl) pop_cframe(hcl)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define POP_ALL_CFRAMES(hcl) (hcl->c->cfs.top = -1)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define GET_TOP_CFRAME_INDEX(hcl) (hcl->c->cfs.top)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define GET_TOP_CFRAME(hcl) (&hcl->c->cfs.ptr[hcl->c->cfs.top])
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define GET_CFRAME(hcl,index) (&hcl->c->cfs.ptr[index])
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define SWITCH_TOP_CFRAME(hcl,_opcode,_operand) \
 | 
					
						
							|  |  |  | 	do { \ | 
					
						
							|  |  |  | 		hcl_cframe_t* _cf = GET_TOP_CFRAME(hcl); \ | 
					
						
							|  |  |  | 		_cf->opcode = _opcode; \ | 
					
						
							|  |  |  | 		_cf->operand = _operand; \ | 
					
						
							|  |  |  | 	} while (0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define SWITCH_CFRAME(hcl,_index,_opcode,_operand) \
 | 
					
						
							|  |  |  | 	do { \ | 
					
						
							|  |  |  | 		hcl_cframe_t* _cf = GET_CFRAME(hcl,_index); \ | 
					
						
							|  |  |  | 		_cf->opcode = _opcode; \ | 
					
						
							|  |  |  | 		_cf->operand = _operand; \ | 
					
						
							|  |  |  | 	} while (0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int push_subcframe (hcl_t* hcl, int opcode, hcl_oop_t operand) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	hcl_cframe_t* cf, tmp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cf = GET_TOP_CFRAME(hcl); | 
					
						
							|  |  |  | 	tmp = *cf; | 
					
						
							|  |  |  | 	cf->opcode = opcode; | 
					
						
							|  |  |  | 	cf->operand = operand; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return push_cframe (hcl, tmp.opcode, tmp.operand); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define PUSH_SUBCFRAME(hcl,opcode,operand) \
 | 
					
						
							|  |  |  | 	do { if (push_subcframe(hcl,opcode,operand) <= -1) return -1; } while(0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define GET_SUBCFRAME(hcl) (&hcl->c->cfs.ptr[hcl->c->cfs.top - 1])
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | enum  | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	COP_COMPILE_OBJECT, | 
					
						
							|  |  |  | 	COP_COMPILE_OBJECT_LIST, | 
					
						
							|  |  |  | 	COP_COMPILE_ARGUMENT_LIST, | 
					
						
							|  |  |  | 	COP_EMIT_POP, | 
					
						
							|  |  |  | 	COP_EMIT_CALL, | 
					
						
							|  |  |  | 	COP_EMIT_LAMBDA, | 
					
						
							|  |  |  | 	COP_EMIT_SET | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ========================================================================= */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int compile_lambda (hcl_t* hcl, hcl_oop_t src) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-10-01 04:36:48 +00:00
										 |  |  | 	hcl_oop_t obj, args; | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 	hcl_oow_t nargs, ntmprs; | 
					
						
							|  |  |  | 	hcl_oow_t jump_inst_pos; | 
					
						
							| 
									
										
										
										
											2016-10-01 04:36:48 +00:00
										 |  |  | 	hcl_oow_t saved_tv_count, tv_dup_start; | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	HCL_ASSERT (HCL_BRANDOF(hcl,src) == HCL_BRAND_CONS); | 
					
						
							|  |  |  | 	HCL_ASSERT (HCL_CONS_CAR(src) == hcl->_lambda); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-29 13:20:09 +00:00
										 |  |  | 	saved_tv_count = hcl->c->tv.size; | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 	obj = HCL_CONS_CDR(src); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (HCL_IS_NIL(hcl, obj)) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		HCL_DEBUG1 (hcl, "Syntax error - no argument list in lambda - %O\n", src); | 
					
						
							|  |  |  | 		hcl_setsynerr (hcl, HCL_SYNERR_ARGNAMELIST, HCL_NULL, HCL_NULL); /* TODO: error location */ | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if (HCL_BRANDOF(hcl, obj) != HCL_BRAND_CONS) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		HCL_DEBUG1 (hcl, "Syntax error - redundant cdr in lambda - %O\n", src); | 
					
						
							|  |  |  | 		hcl_setsynerr (hcl, HCL_SYNERR_DOTBANNED, HCL_NULL, HCL_NULL); /* TODO: error location */ | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	args = HCL_CONS_CAR(obj); | 
					
						
							|  |  |  | 	if (HCL_IS_NIL(hcl, args)) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		/* no argument - (lambda () (+ 10 20)) */ | 
					
						
							|  |  |  | 		nargs = 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2016-10-01 04:36:48 +00:00
										 |  |  | 		hcl_oop_t arg, ptr; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 		if (HCL_BRANDOF(hcl, args) != HCL_BRAND_CONS) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			HCL_DEBUG1 (hcl, "Syntax error - not a lambda argument list - %O\n", args); | 
					
						
							|  |  |  | 			hcl_setsynerr (hcl, HCL_SYNERR_ARGNAMELIST, HCL_NULL, HCL_NULL); /* TODO: error location */ | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-29 13:20:09 +00:00
										 |  |  | 		tv_dup_start = hcl->c->tv.size; | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 		nargs = 0; | 
					
						
							|  |  |  | 		ptr = args; | 
					
						
							|  |  |  | 		do | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			arg = HCL_CONS_CAR(ptr); | 
					
						
							|  |  |  | 			if (HCL_BRANDOF(hcl, arg) != HCL_BRAND_SYMBOL) | 
					
						
							|  |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2016-09-29 13:20:09 +00:00
										 |  |  | 				HCL_DEBUG1 (hcl, "Syntax error - lambda argument not a symbol - %O\n", arg); | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 				hcl_setsynerr (hcl, HCL_SYNERR_ARGNAME, HCL_NULL, HCL_NULL); /* TODO: error location */ | 
					
						
							|  |  |  | 				return -1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 	/* TODO: check duplicates within only the argument list. duplicates against outer-scope are ok.
 | 
					
						
							|  |  |  | 	 * is this check necessary? */ | 
					
						
							| 
									
										
										
										
											2016-09-29 13:20:09 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			if (add_temporary_variable (hcl, arg, tv_dup_start) <= -1)  | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				if (hcl->errnum == HCL_EEXIST) | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					HCL_DEBUG1 (hcl, "Syntax error - lambda argument duplicate - %O\n", arg); | 
					
						
							| 
									
										
										
										
											2016-10-01 04:36:48 +00:00
										 |  |  | 					hcl_setsynerr (hcl, HCL_SYNERR_ARGNAMEDUP, HCL_NULL, HCL_NULL); /* TODO: error location */ | 
					
						
							| 
									
										
										
										
											2016-09-29 13:20:09 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 				return -1; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 			nargs++; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			ptr = HCL_CONS_CDR(ptr); | 
					
						
							|  |  |  | 			if (HCL_BRANDOF(hcl, ptr) != HCL_BRAND_CONS)  | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				if (!HCL_IS_NIL(hcl, ptr)) | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					HCL_DEBUG1 (hcl, "Syntax error - redundant cdr in lambda argument list - %O\n", args); | 
					
						
							|  |  |  | 					hcl_setsynerr (hcl, HCL_SYNERR_DOTBANNED, HCL_NULL, HCL_NULL); /* TODO: error location */ | 
					
						
							|  |  |  | 					return -1; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		while (1); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-29 13:20:09 +00:00
										 |  |  | 	HCL_ASSERT (nargs == hcl->c->tv.size - saved_tv_count); | 
					
						
							|  |  |  | 	if (nargs > MAX_CODE_NBLKARGS) /*TODO: change this limit to max call argument count */ | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		/* while an integer object is pused to indicate the number of
 | 
					
						
							|  |  |  | 		 * block arguments, evaluation which is done by message passing | 
					
						
							|  |  |  | 		 * limits the number of arguments that can be passed. so the | 
					
						
							|  |  |  | 		 * check is implemented */ | 
					
						
							|  |  |  | 		HCL_DEBUG1 (hcl, "Syntax error - too many arguments - %O\n", args); | 
					
						
							|  |  |  | 		hcl_setsynerr (hcl, HCL_SYNERR_ARGFLOOD, HCL_NULL, HCL_NULL);  | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-01 04:36:48 +00:00
										 |  |  | 	ntmprs = nargs;   | 
					
						
							|  |  |  | 	obj = HCL_CONS_CDR(obj); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	tv_dup_start = hcl->c->tv.size; | 
					
						
							|  |  |  | 	while (HCL_IS_CONS(hcl, obj)) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		hcl_oop_t dcl; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		dcl = HCL_CONS_CAR(obj); | 
					
						
							|  |  |  | 		if (HCL_IS_SYMBOL_ARRAY(hcl, dcl)) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			hcl_oow_t i, sz; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			sz = HCL_OBJ_GET_SIZE(dcl); | 
					
						
							|  |  |  | 			for (i = 0; i < sz; i++) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				if (add_temporary_variable (hcl, ((hcl_oop_oop_t)dcl)->slot[i], tv_dup_start) <= -1)  | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					if (hcl->errnum == HCL_EEXIST) | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						HCL_DEBUG1 (hcl, "Syntax error - local variable duplicate - %O\n", ((hcl_oop_oop_t)dcl)->slot[i]); | 
					
						
							|  |  |  | 						hcl_setsynerr (hcl, HCL_SYNERR_VARNAMEDUP, HCL_NULL, HCL_NULL); /* TODO: error location */ | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					return -1; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				ntmprs++; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			obj = HCL_CONS_CDR(obj); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-29 13:20:09 +00:00
										 |  |  | 	/* ntmprs: number of temporary variables including arguments */ | 
					
						
							|  |  |  | 	HCL_ASSERT (ntmprs == hcl->c->tv.size - saved_tv_count); | 
					
						
							|  |  |  | 	if (ntmprs > MAX_CODE_NBLKTMPRS) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2016-10-01 04:36:48 +00:00
										 |  |  | 		HCL_DEBUG1 (hcl, "Syntax error - too many variables - %O\n", args); | 
					
						
							|  |  |  | 		hcl_setsynerr (hcl, HCL_SYNERR_VARFLOOD, HCL_NULL, HCL_NULL);  | 
					
						
							| 
									
										
										
										
											2016-09-29 13:20:09 +00:00
										 |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (hcl->c->blk.depth == HCL_TYPE_MAX(hcl_ooi_t)) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		HCL_DEBUG1 (hcl, "Syntax error - lambda block depth too deep - %O\n", src); | 
					
						
							|  |  |  | 		hcl_setsynerr (hcl, HCL_SYNERR_BLKDEPTH, HCL_NULL, HCL_NULL);  | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	hcl->c->blk.depth++; | 
					
						
							|  |  |  | 	if (store_temporary_variable_count_for_block (hcl, hcl->c->tv.size) <= -1) return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-08 17:22:48 +00:00
										 |  |  | 	/* use the accumulated number of temporaries so far when generating
 | 
					
						
							|  |  |  | 	 * the make_block instruction. at context activation time, the actual  | 
					
						
							|  |  |  | 	 * count of temporaries for this block is derived by subtracting the  | 
					
						
							|  |  |  | 	 * count of temporaries in the home context */ | 
					
						
							|  |  |  | 	if (emit_double_param_instruction (hcl, HCL_CODE_MAKE_BLOCK, nargs, hcl->c->tv.size/*ntmprs*/) <= -1) return -1; | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* specifying MAX_CODE_JUMP causes emit_single_param_instruction() to 
 | 
					
						
							|  |  |  | 	 * produce the long jump instruction (BCODE_JUMP_FORWARD_X) */ | 
					
						
							|  |  |  | 	jump_inst_pos = hcl->code.bc.len; | 
					
						
							|  |  |  | 	if (emit_single_param_instruction (hcl, HCL_CODE_JUMP_FORWARD_0, MAX_CODE_JUMP) <= -1) return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-01 04:36:48 +00:00
										 |  |  | 	SWITCH_TOP_CFRAME (hcl, COP_COMPILE_OBJECT_LIST, obj); | 
					
						
							| 
									
										
										
										
											2016-09-29 13:20:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-08 17:22:48 +00:00
										 |  |  | 	HCL_ASSERT (jump_inst_pos < HCL_SMOOI_MAX); /* guaranteed in emit_byte_instruction() */ | 
					
						
							|  |  |  | 	PUSH_SUBCFRAME (hcl, COP_EMIT_LAMBDA, HCL_SMOOI_TO_OOP(jump_inst_pos)); | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int compile_set (hcl_t* hcl, hcl_oop_t src) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	hcl_cframe_t* cf; | 
					
						
							|  |  |  | 	hcl_oop_t obj, var, val; | 
					
						
							| 
									
										
										
										
											2016-10-01 04:36:48 +00:00
										 |  |  | 	hcl_oow_t index; | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	obj = HCL_CONS_CDR(src); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	HCL_ASSERT (HCL_BRANDOF(hcl,src) == HCL_BRAND_CONS); | 
					
						
							|  |  |  | 	HCL_ASSERT (HCL_CONS_CAR(src) == hcl->_set); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (HCL_IS_NIL(hcl, obj)) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		HCL_DEBUG1 (hcl, "Syntax error - no variable name in set - %O\n", src); | 
					
						
							|  |  |  | 		hcl_setsynerr (hcl, HCL_SYNERR_VARNAME, HCL_NULL, HCL_NULL); /* TODO: error location */ | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if (HCL_BRANDOF(hcl, obj) != HCL_BRAND_CONS) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		HCL_DEBUG1 (hcl, "Syntax error - redundant cdr in set - %O\n", src); | 
					
						
							|  |  |  | 		hcl_setsynerr (hcl, HCL_SYNERR_DOTBANNED, HCL_NULL, HCL_NULL); /* TODO: error location */ | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var = HCL_CONS_CAR(obj); | 
					
						
							|  |  |  | 	if (HCL_BRANDOF(hcl, var) != HCL_BRAND_SYMBOL) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		HCL_DEBUG1 (hcl, "Syntax error - variable name not a symbol - %O\n", var); | 
					
						
							|  |  |  | 		hcl_setsynerr (hcl, HCL_SYNERR_VARNAME, HCL_NULL, HCL_NULL); /* TODO: error location */ | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	obj = HCL_CONS_CDR(obj); | 
					
						
							|  |  |  | 	if (HCL_IS_NIL(hcl, obj)) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		/* no value */ | 
					
						
							|  |  |  | 		HCL_DEBUG1 (hcl, "Syntax error - no value specified in set - %O\n", src); | 
					
						
							|  |  |  | 		hcl_setsynerr (hcl, HCL_SYNERR_ARGCOUNT, HCL_NULL, HCL_NULL); /* TODO: error location */ | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if (HCL_BRANDOF(hcl, obj) != HCL_BRAND_CONS) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		HCL_DEBUG1 (hcl, "Syntax error - redundant cdr in set - %O\n", src); | 
					
						
							|  |  |  | 		hcl_setsynerr (hcl, HCL_SYNERR_DOTBANNED, HCL_NULL, HCL_NULL); /* TODO: error location */ | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	val = HCL_CONS_CAR(obj); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	obj = HCL_CONS_CDR(obj); | 
					
						
							|  |  |  | 	if (!HCL_IS_NIL(hcl, obj)) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		HCL_DEBUG1 (hcl, "Synatx error - too many arguments to set - %O\n", src); | 
					
						
							|  |  |  | 		hcl_setsynerr (hcl, HCL_SYNERR_ARGCOUNT, HCL_NULL, HCL_NULL); /* TODO: error location */ | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	SWITCH_TOP_CFRAME (hcl, COP_COMPILE_OBJECT, val); | 
					
						
							| 
									
										
										
										
											2016-10-01 04:36:48 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (find_temporary_variable_backward (hcl, var, &index) <= -1) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		PUSH_SUBCFRAME (hcl, COP_EMIT_SET, var); /* set doesn't evaluate the variable name */ | 
					
						
							|  |  |  | 		cf = GET_SUBCFRAME (hcl); | 
					
						
							|  |  |  | 		cf->u.set.var_type = VAR_NAMED; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		/* the check in compile_lambda() must ensure this condition */ | 
					
						
							|  |  |  | 		HCL_ASSERT (index <= HCL_SMOOI_MAX);  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		PUSH_SUBCFRAME (hcl, COP_EMIT_SET, HCL_SMOOI_TO_OOP(index));  | 
					
						
							|  |  |  | 		cf = GET_SUBCFRAME (hcl); | 
					
						
							|  |  |  | 		cf->u.set.var_type = VAR_INDEXED; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int compile_cons (hcl_t* hcl, hcl_oop_t obj) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	hcl_oop_t car; | 
					
						
							|  |  |  | 	int syncode; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	HCL_ASSERT (HCL_BRANDOF(hcl,obj) == HCL_BRAND_CONS); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	car = HCL_CONS_CAR(obj); | 
					
						
							|  |  |  | 	if (HCL_BRANDOF(hcl,car) == HCL_BRAND_SYMBOL && (syncode = HCL_OBJ_GET_FLAGS_SYNCODE(car))) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		switch (syncode) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			case HCL_SYNCODE_BEGIN: | 
					
						
							|  |  |  | 			case HCL_SYNCODE_DEFUN: | 
					
						
							|  |  |  | 			case HCL_SYNCODE_IF: | 
					
						
							|  |  |  | 				/* TODO: */ | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			case HCL_SYNCODE_LAMBDA: | 
					
						
							|  |  |  | 				/* (lambda (x y) (+ x y)) */ | 
					
						
							|  |  |  | 				if (compile_lambda (hcl, obj) <= -1) return -1; | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			case HCL_SYNCODE_SET: | 
					
						
							|  |  |  | 				/* (set x 10) 
 | 
					
						
							|  |  |  | 				 * (set x (lambda (x y) (+ x y)) */ | 
					
						
							|  |  |  | 				if (compile_set (hcl, obj) <= -1) return -1; | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			default: | 
					
						
							|  |  |  | 				HCL_DEBUG3 (hcl, "Internal error - unknown syncode %d at %s:%d\n", syncode, __FILE__, __LINE__); | 
					
						
							|  |  |  | 				hcl->errnum = HCL_EINTERN; | 
					
						
							|  |  |  | 				return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		/* normal function call 
 | 
					
						
							|  |  |  | 		 *  (<operator> <operand1> ...) */ | 
					
						
							|  |  |  | 		hcl_ooi_t nargs; | 
					
						
							|  |  |  | 		hcl_oow_t oldtop; | 
					
						
							|  |  |  | 		hcl_cframe_t* cf; | 
					
						
							|  |  |  | 		hcl_oop_t cdr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* NOTE: cframe management functions don't use the object memory.
 | 
					
						
							|  |  |  | 		 *       many operations can be performed without taking GC into account */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		oldtop = GET_TOP_CFRAME_INDEX(hcl); | 
					
						
							|  |  |  | 		HCL_ASSERT (oldtop >= 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		SWITCH_TOP_CFRAME (hcl, COP_EMIT_CALL, HCL_SMOOI_TO_OOP(0)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* compile <operator> */ | 
					
						
							|  |  |  | 		PUSH_CFRAME (hcl, COP_COMPILE_OBJECT, car); | 
					
						
							|  |  |  | /* TODO: do pre-filtering. if car is a literal, it's not a valid function call - this can also be check in the reader.
 | 
					
						
							|  |  |  |  *       if it's a symbol and it evaluates to a literal, it can only be caught in the runtime   | 
					
						
							|  |  |  | * this check along with the .cdr check, can be done in the reader if i create a special flag (e.g. QUOTED) applicable to CONS. | 
					
						
							|  |  |  | * what happens if someone likes to manipulate the list as the list is not a single object type unlike array??? | 
					
						
							|  |  |  | *     (define (x y) (10 20 30)) | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* compile <operand1> ... etc */ | 
					
						
							|  |  |  | 		cdr = HCL_CONS_CDR(obj); | 
					
						
							|  |  |  | 		if (HCL_IS_NIL(hcl, cdr))  | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			nargs = 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			if (HCL_BRANDOF(hcl, cdr) != HCL_BRAND_CONS) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				HCL_DEBUG1 (hcl, "Syntax error - redundant cdr in function call - %O\n", obj); | 
					
						
							|  |  |  | 				hcl_setsynerr (hcl, HCL_SYNERR_DOTBANNED, HCL_NULL, HCL_NULL); /* TODO: error location */ | 
					
						
							|  |  |  | 				return -1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			nargs = hcl_countcons (hcl, cdr); | 
					
						
							|  |  |  | 			if (nargs > MAX_CODE_PARAM)  | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				hcl->errnum = HCL_ETOOBIG; /* TODO: change the error code to a better one */ | 
					
						
							|  |  |  | 				return -1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		/* redundant cdr check is performed inside compile_object_list() */ | 
					
						
							|  |  |  | 		PUSH_SUBCFRAME (hcl, COP_COMPILE_ARGUMENT_LIST, cdr); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* patch the argument count in the operand field of the COP_EMIT_CALL frame */ | 
					
						
							|  |  |  | 		cf = GET_CFRAME(hcl, oldtop); | 
					
						
							|  |  |  | 		HCL_ASSERT (cf->opcode == COP_EMIT_CALL); | 
					
						
							|  |  |  | 		cf->operand = HCL_SMOOI_TO_OOP(nargs); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-01 04:36:48 +00:00
										 |  |  | static int emit_indexed_variable_access (hcl_t* hcl, hcl_oow_t index, hcl_oob_t baseinst1, hcl_oob_t baseinst2) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #if defined(HCL_USE_CTXTEMPVAR)
 | 
					
						
							|  |  |  | 	if (hcl->c->blk.depth >= 0) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		hcl_oow_t i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* if a temporary variable is accessed inside a block,
 | 
					
						
							|  |  |  | 		 * use a special instruction to indicate it */ | 
					
						
							|  |  |  | 		HCL_ASSERT (index < hcl->c->blk.tmprcnt[hcl->c->blk.depth]); | 
					
						
							|  |  |  | 		for (i = hcl->c->blk.depth; i > 0; i--) /* excluded the top level -- TODO: change this code depending on global variable handling */ | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			if (index >= hcl->c->blk.tmprcnt[i - 1]) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				hcl_oow_t ctx_offset, index_in_ctx; | 
					
						
							|  |  |  | 				ctx_offset = hcl->c->blk.depth - i; | 
					
						
							|  |  |  | 				index_in_ctx = index - hcl->c->blk.tmprcnt[i - 1]; | 
					
						
							|  |  |  | 				/* ctx_offset 0 means the current context.
 | 
					
						
							|  |  |  | 				 *            1 means current->home. | 
					
						
							|  |  |  | 				 *            2 means current->home->home.  | 
					
						
							|  |  |  | 				 * index_in_ctx is a relative index within the context found. | 
					
						
							|  |  |  | 				 */ | 
					
						
							|  |  |  | 				if (emit_double_param_instruction(hcl, baseinst1, ctx_offset, index_in_ctx) <= -1) return -1; | 
					
						
							|  |  |  | 				return 0; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* TODO: top-level... verify this. this will vary depending on how i implement the top-level and global variables... */ | 
					
						
							|  |  |  | 	if (emit_single_param_instruction (hcl, baseinst2, index) <= -1) return -1; | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | static HCL_INLINE int compile_symbol (hcl_t* hcl, hcl_oop_t obj) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	hcl_oow_t index; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	HCL_ASSERT (HCL_BRANDOF(hcl,obj) == HCL_BRAND_SYMBOL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* check if a symbol is a local variable */ | 
					
						
							| 
									
										
										
										
											2016-09-29 13:20:09 +00:00
										 |  |  | 	if (find_temporary_variable_backward (hcl, obj, &index) <= -1) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2016-10-04 17:56:28 +00:00
										 |  |  | 		hcl_oop_t cons; | 
					
						
							| 
									
										
										
										
											2016-10-01 04:36:48 +00:00
										 |  |  | /* TODO: if i require all variables to be declared, this part is not needed and should handle it as an error */ | 
					
						
							| 
									
										
										
										
											2016-10-04 17:56:28 +00:00
										 |  |  | /* TODO: change the scheme... allow declaration??? */ | 
					
						
							| 
									
										
										
										
											2016-09-29 13:20:09 +00:00
										 |  |  | 		/* global variable */ | 
					
						
							| 
									
										
										
										
											2016-10-04 17:56:28 +00:00
										 |  |  | 		cons = (hcl_oop_t)hcl_getatsysdic (hcl, obj); | 
					
						
							|  |  |  | 		if (!cons)  | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			cons = (hcl_oop_t)hcl_putatsysdic (hcl, obj, hcl->_nil); | 
					
						
							|  |  |  | 			if (!cons) return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (add_literal(hcl, cons, &index) <= -1 || | 
					
						
							| 
									
										
										
										
											2016-09-29 13:20:09 +00:00
										 |  |  | 		    emit_single_param_instruction (hcl, HCL_CODE_PUSH_OBJECT_0, index) <= -1) return -1; | 
					
						
							| 
									
										
										
										
											2016-10-01 04:36:48 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		return 0; | 
					
						
							| 
									
										
										
										
											2016-09-29 13:20:09 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2016-10-01 04:36:48 +00:00
										 |  |  | 		return emit_indexed_variable_access (hcl, index, HCL_CODE_PUSH_CTXTEMPVAR_0, HCL_CODE_PUSH_TEMPVAR_0); | 
					
						
							| 
									
										
										
										
											2016-09-29 13:20:09 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int compile_object (hcl_t* hcl) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	hcl_cframe_t* cf; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cf = GET_TOP_CFRAME(hcl); | 
					
						
							|  |  |  | 	HCL_ASSERT (cf->opcode == COP_COMPILE_OBJECT); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (HCL_OOP_IS_NUMERIC(cf->operand)) goto literal; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	switch (HCL_OBJ_GET_FLAGS_BRAND(cf->operand)) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		case HCL_BRAND_NIL: | 
					
						
							|  |  |  | 			EMIT_BYTE_INSTRUCTION (hcl, HCL_CODE_PUSH_NIL); | 
					
						
							|  |  |  | 			goto done; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case HCL_BRAND_TRUE: | 
					
						
							|  |  |  | 			EMIT_BYTE_INSTRUCTION (hcl, HCL_CODE_PUSH_TRUE); | 
					
						
							|  |  |  | 			goto done; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case HCL_BRAND_FALSE: | 
					
						
							|  |  |  | 			EMIT_BYTE_INSTRUCTION (hcl, HCL_CODE_PUSH_FALSE); | 
					
						
							|  |  |  | 			goto done; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case HCL_BRAND_SYMBOL: | 
					
						
							|  |  |  | 			if (compile_symbol(hcl, cf->operand) <= -1) return -1; | 
					
						
							|  |  |  | 			goto done; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case HCL_BRAND_CONS: | 
					
						
							|  |  |  | 			if (compile_cons (hcl, cf->operand) <= -1) return -1; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-01 04:36:48 +00:00
										 |  |  | 		case HCL_BRAND_SYMBOL_ARRAY: | 
					
						
							|  |  |  | 			HCL_DEBUG1 (hcl, "Syntax error - variable declartion disallowed - %O\n", cf->operand); | 
					
						
							|  |  |  | 			hcl_setsynerr (hcl, HCL_SYNERR_VARDCLBANNED, HCL_NULL, HCL_NULL); /* TODO: error location */ | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 		default: | 
					
						
							|  |  |  | 			goto literal; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | literal: | 
					
						
							|  |  |  | 	if (emit_push_literal (hcl, cf->operand) <= -1) return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | done: | 
					
						
							|  |  |  | 	POP_CFRAME (hcl); | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int compile_object_list (hcl_t* hcl) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	hcl_cframe_t* cf; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cf = GET_TOP_CFRAME(hcl); | 
					
						
							|  |  |  | 	HCL_ASSERT (cf->opcode == COP_COMPILE_OBJECT_LIST || | 
					
						
							|  |  |  | 	            cf->opcode == COP_COMPILE_ARGUMENT_LIST); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (HCL_IS_NIL(hcl, cf->operand)) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		POP_CFRAME (hcl); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		hcl_oop_t car, cdr; | 
					
						
							|  |  |  | 		int cop; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (HCL_BRANDOF(hcl, cf->operand) != HCL_BRAND_CONS) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			HCL_DEBUG1 (hcl, "Syntax error - redundant cdr in the object list - %O\n", cf->operand); | 
					
						
							|  |  |  | 			hcl_setsynerr (hcl, HCL_SYNERR_DOTBANNED, HCL_NULL, HCL_NULL); /* TODO: error location */ | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		cop = cf->opcode; | 
					
						
							|  |  |  | 		car = HCL_CONS_CAR(cf->operand); | 
					
						
							|  |  |  | 		cdr = HCL_CONS_CDR(cf->operand); | 
					
						
							|  |  |  | 		SWITCH_TOP_CFRAME (hcl, COP_COMPILE_OBJECT, car); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (!HCL_IS_NIL(hcl, cdr)) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			/* (+ 1 2 3) - argument list. 1, 2, 3 pushed must remain in 
 | 
					
						
							|  |  |  | 			 *             the stack until the function '+' is called. | 
					
						
							|  |  |  | 			 * | 
					
						
							|  |  |  | 			 * (lambda (x y) (+ x 10) (+ y 20))  | 
					
						
							|  |  |  | 			 *    - the result of (+ x 10) should be popped before (+ y 20) | 
					
						
							|  |  |  | 			 *      is executed  | 
					
						
							|  |  |  | 			 */ | 
					
						
							|  |  |  | 			PUSH_SUBCFRAME (hcl, cop, cdr); | 
					
						
							|  |  |  | 			if (cop == COP_COMPILE_OBJECT_LIST) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				/* let's arrange to emit POP before generating code for the rest of the list */ | 
					
						
							|  |  |  | 				PUSH_SUBCFRAME (hcl, COP_EMIT_POP, hcl->_nil); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static HCL_INLINE int emit_lambda (hcl_t* hcl) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	hcl_cframe_t* cf; | 
					
						
							|  |  |  | 	hcl_oow_t block_code_size; | 
					
						
							| 
									
										
										
										
											2016-10-08 17:22:48 +00:00
										 |  |  | 	hcl_oow_t jip; | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	cf = GET_TOP_CFRAME(hcl); | 
					
						
							|  |  |  | 	HCL_ASSERT (cf->opcode == COP_EMIT_LAMBDA); | 
					
						
							| 
									
										
										
										
											2016-10-08 17:22:48 +00:00
										 |  |  | 	HCL_ASSERT (HCL_OOP_IS_SMOOI(cf->operand)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	jip = HCL_OOP_TO_SMOOI(cf->operand); | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-29 13:20:09 +00:00
										 |  |  | 	hcl->c->blk.depth--; | 
					
						
							|  |  |  | 	hcl->c->tv.size = hcl->c->blk.tmprcnt[hcl->c->blk.depth]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 	/* HCL_CODE_LONG_PARAM_SIZE + 1 => size of the long JUMP_FORWARD instruction */ | 
					
						
							| 
									
										
										
										
											2016-10-08 17:22:48 +00:00
										 |  |  | 	block_code_size = hcl->code.bc.len - jip - (HCL_BCODE_LONG_PARAM_SIZE + 1); | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (block_code_size == 0) | 
					
						
							|  |  |  |  	{ | 
					
						
							|  |  |  | 		/* no body in lambda - (lambda (a b c)) */ | 
					
						
							|  |  |  | /* TODO: is this correct??? */ | 
					
						
							|  |  |  | 		if (emit_byte_instruction(hcl, HCL_CODE_PUSH_NIL) <= -1) return -1; | 
					
						
							| 
									
										
										
										
											2016-10-04 17:56:28 +00:00
										 |  |  | 		block_code_size++; | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (emit_byte_instruction (hcl, HCL_CODE_RETURN_FROM_BLOCK) <= -1) return -1; | 
					
						
							| 
									
										
										
										
											2016-10-04 17:56:28 +00:00
										 |  |  | 	block_code_size++; | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (block_code_size > MAX_CODE_JUMP * 2) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		HCL_DEBUG1 (hcl, "Too big a lambda block - size %zu\n", block_code_size); | 
					
						
							|  |  |  | 		hcl_setsynerr (hcl, HCL_SYNERR_BLKFLOOD, HCL_NULL, HCL_NULL); /* error location */ | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else  | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		hcl_oow_t jump_offset; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (block_code_size > MAX_CODE_JUMP) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			/* switch to JUMP2 instruction to allow a bigger jump offset.
 | 
					
						
							|  |  |  | 			 * up to twice MAX_CODE_JUMP only */ | 
					
						
							| 
									
										
										
										
											2016-10-08 17:22:48 +00:00
										 |  |  | 			patch_instruction (hcl, jip, HCL_CODE_JUMP2_FORWARD); | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 			jump_offset = block_code_size - MAX_CODE_JUMP; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			jump_offset = block_code_size; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	#if (HCL_BCODE_LONG_PARAM_SIZE == 2)
 | 
					
						
							| 
									
										
										
										
											2016-10-08 17:22:48 +00:00
										 |  |  | 		patch_instruction (hcl, jip + 1, jump_offset >> 8); | 
					
						
							|  |  |  | 		patch_instruction (hcl, jip + 2, jump_offset & 0xFF); | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 	#else
 | 
					
						
							| 
									
										
										
										
											2016-10-08 17:22:48 +00:00
										 |  |  | 		patch_instruction (hcl, jip + 1, jump_offset); | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 	#endif
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	POP_CFRAME (hcl); | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static HCL_INLINE int emit_pop (hcl_t* hcl) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	hcl_cframe_t* cf; | 
					
						
							|  |  |  | 	int n; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cf = GET_TOP_CFRAME(hcl); | 
					
						
							|  |  |  | 	HCL_ASSERT (cf->opcode == COP_EMIT_POP); | 
					
						
							|  |  |  | 	HCL_ASSERT (HCL_IS_NIL(hcl, cf->operand)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	n = emit_byte_instruction (hcl, HCL_CODE_POP_STACKTOP); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	POP_CFRAME (hcl); | 
					
						
							|  |  |  | 	return n; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static HCL_INLINE int emit_call (hcl_t* hcl) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	hcl_cframe_t* cf; | 
					
						
							|  |  |  | 	int n; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cf = GET_TOP_CFRAME(hcl); | 
					
						
							|  |  |  | 	HCL_ASSERT (cf->opcode == COP_EMIT_CALL); | 
					
						
							|  |  |  | 	HCL_ASSERT (HCL_OOP_IS_SMOOI(cf->operand)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	n = emit_single_param_instruction (hcl, HCL_CODE_CALL_0, HCL_OOP_TO_SMOOI(cf->operand)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	POP_CFRAME (hcl); | 
					
						
							|  |  |  | 	return n; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static HCL_INLINE int emit_set (hcl_t* hcl) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	hcl_cframe_t* cf; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cf = GET_TOP_CFRAME(hcl); | 
					
						
							|  |  |  | 	HCL_ASSERT (cf->opcode == COP_EMIT_SET); | 
					
						
							| 
									
										
										
										
											2016-10-01 04:36:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (cf->u.set.var_type == VAR_NAMED) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		hcl_oow_t index; | 
					
						
							| 
									
										
										
										
											2016-10-04 17:56:28 +00:00
										 |  |  | 		hcl_oop_t cons; | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-01 04:36:48 +00:00
										 |  |  | 		HCL_ASSERT (HCL_IS_SYMBOL(hcl, cf->operand)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-04 17:56:28 +00:00
										 |  |  | 		cons = (hcl_oop_t)hcl_getatsysdic (hcl, cf->operand); | 
					
						
							|  |  |  | 		if (!cons)  | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			cons = (hcl_oop_t)hcl_putatsysdic (hcl, cf->operand, hcl->_nil); | 
					
						
							|  |  |  | 			if (!cons) return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (add_literal(hcl, cons, &index) <= -1 || | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 		    emit_single_param_instruction(hcl, HCL_CODE_STORE_INTO_OBJECT_0, index) <= -1) return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2016-10-01 04:36:48 +00:00
										 |  |  | 		hcl_oow_t index; | 
					
						
							|  |  |  | 		HCL_ASSERT (cf->u.set.var_type == VAR_INDEXED); | 
					
						
							|  |  |  | 		HCL_ASSERT (HCL_OOP_IS_SMOOI(cf->operand)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		index = (hcl_oow_t)HCL_OOP_TO_SMOOI(cf->operand); | 
					
						
							|  |  |  | 		if (emit_indexed_variable_access (hcl, index, HCL_CODE_STORE_INTO_CTXTEMPVAR_0, HCL_CODE_STORE_INTO_TEMPVAR_0) <= -1) return -1; | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	POP_CFRAME (hcl); | 
					
						
							|  |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2016-10-01 04:36:48 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | int hcl_compile (hcl_t* hcl, hcl_oop_t obj) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	hcl_oow_t saved_bc_len, saved_lit_len; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	HCL_ASSERT (GET_TOP_CFRAME_INDEX(hcl) < 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	saved_bc_len = hcl->code.bc.len; | 
					
						
							|  |  |  | 	saved_lit_len = hcl->code.lit.len; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-29 13:20:09 +00:00
										 |  |  | 	HCL_ASSERT (hcl->c->tv.size == 0); | 
					
						
							|  |  |  | 	HCL_ASSERT (hcl->c->blk.depth == -1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* TODO: in case i implement all global variables as block arguments at the top level... */ | 
					
						
							|  |  |  | 	hcl->c->blk.depth++; | 
					
						
							|  |  |  | 	if (store_temporary_variable_count_for_block(hcl, hcl->c->tv.size) <= -1) return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 	PUSH_CFRAME (hcl, COP_COMPILE_OBJECT, obj); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while (GET_TOP_CFRAME_INDEX(hcl) >= 0) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		hcl_cframe_t* cf; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		cf = GET_TOP_CFRAME(hcl); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		switch (cf->opcode) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			case COP_COMPILE_OBJECT: | 
					
						
							|  |  |  | 				if (compile_object (hcl) <= -1) goto oops; | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			case COP_COMPILE_OBJECT_LIST: | 
					
						
							|  |  |  | 			case COP_COMPILE_ARGUMENT_LIST: | 
					
						
							|  |  |  | 				if (compile_object_list (hcl) <= -1) goto oops; | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			case COP_EMIT_POP: | 
					
						
							|  |  |  | 				if (emit_pop (hcl) <= -1) goto oops; | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			case COP_EMIT_CALL: | 
					
						
							|  |  |  | 				if (emit_call (hcl) <= -1) goto oops; | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			case COP_EMIT_LAMBDA: | 
					
						
							|  |  |  | 				if (emit_lambda (hcl) <= -1) goto oops; | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			case COP_EMIT_SET: | 
					
						
							|  |  |  | 				if (emit_set (hcl) <= -1) goto oops; | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			default: | 
					
						
							|  |  |  | 				hcl->errnum = HCL_EINTERN; | 
					
						
							|  |  |  | 				goto oops; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-06 17:49:47 +00:00
										 |  |  | 	/* emit the pop instruction to clear the final result */ | 
					
						
							|  |  |  | /* TODO: for interactive use, this value must be accessible by the executor... how to do it? */ | 
					
						
							|  |  |  | 	if (emit_byte_instruction (hcl, HCL_CODE_POP_STACKTOP) <= -1) goto oops; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 	HCL_ASSERT (GET_TOP_CFRAME_INDEX(hcl) < 0); | 
					
						
							| 
									
										
										
										
											2016-09-29 13:20:09 +00:00
										 |  |  | 	HCL_ASSERT (hcl->c->tv.size == 0); | 
					
						
							|  |  |  | 	HCL_ASSERT (hcl->c->blk.depth == 0); | 
					
						
							|  |  |  | 	hcl->c->blk.depth--; | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | oops: | 
					
						
							|  |  |  | 	POP_ALL_CFRAMES (hcl); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* rollback any bytecodes or literals emitted so far */ | 
					
						
							|  |  |  | 	hcl->code.bc.len = saved_bc_len; | 
					
						
							|  |  |  | 	hcl->code.lit.len = saved_lit_len; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-29 13:20:09 +00:00
										 |  |  | 	hcl->c->tv.size = 0; | 
					
						
							| 
									
										
										
										
											2016-10-01 04:36:48 +00:00
										 |  |  | 	hcl->c->blk.depth = -1; | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 	return -1; | 
					
						
							|  |  |  | } |