// File: /workspace/github_c_makefile_star2_O0/goodpaul6[P]generic/script.c
// Function: compile_value_expr
static void compile_value_expr(script_t* script, expr_t* exp)
{
	compile_file_line_info(script, exp, 0);
	
	switch(exp->type)
	{
		case EXP_NULL:
		{
			append_code(script, OP_PUSH_NULL);
		} break;
		
		case EXP_STRUCT_NEW:
		{
			char* initialized_members = emalloc(exp->newx.type->ds.members.length);
			memset(initialized_members, 0, exp->newx.type->ds.members.length);
			
			int num_init = 0;
			for(int i = exp->newx.init.length - 1; i >= 0; --i)
			{
				expr_t* init = vec_get_value(&exp->newx.init, i, expr_t*);
				int index = get_struct_type_member_index(exp->newx.type, init->binx.lhs->varx.name);
				
				if(index < 0) error_exit_e(init, "Attempted to initialize non-existent member '%s' in struct %s instantiation\n", 
							  init->binx.lhs->varx.name, exp->newx.type->ds.name);
							  
				initialized_members[index] = 1;
				++num_init;
				
				append_code(script, OP_PUSH_NUMBER);
				append_int(script, register_number(script, index));
				
				compile_value_expr(script, init->binx.rhs);
			}
			
			// NOTE: iterate over all the member types, check if they've been
			// initialized; if they haven't, and they have a default initializer
			// then use that
			for(int i = exp->newx.type->ds.members.length - 1; i >= 0; --i)
			{
				if(!initialized_members[i])
				{
					type_tag_member_t* mem = vec_get(&exp->newx.type->ds.members, i);
					if(mem->default_value)
					{
						append_code(script, OP_PUSH_NUMBER);
						append_int(script, register_number(script, i));
						
						compile_value_expr(script, mem->default_value);
						++num_init;
					}
				}
			}
			
			append_code(script, OP_PUSH_STRUCT);
			// NOTE: Unions only have 1 member location
			if(exp->newx.type->ds.is_union)
				append_int(script, 1);
			else
				append_int(script, exp->newx.type->ds.members.length);
			append_int(script, num_init);
			
			free(initialized_members);
		} break;
		
		case EXP_DOT:
		{
			int index = get_struct_type_member_index(exp->dotx.value->tag, exp->dotx.name);
			if(index < 0) error_exit_e(exp, "Attempted to access non-existent member '%s' in struct %s\n", exp->dotx.name, exp->dotx.value->tag->ds.name);
			
			compile_value_expr(script, exp->dotx.value);
			append_code(script, OP_STRUCT_GET);
			append_int(script, index);		
		} break;

		case EXP_COLON:
		{
			func_decl_t* decl = get_struct_member_function(script, exp->dotx.value->tag->ds.name, exp->dotx.name);
			if (!decl)
				error_exit_e(exp, "Value of type '%s' has no member function '%s'\n", exp->dotx.value->tag->ds.name, exp->dotx.name);

			append_code(script, OP_PUSH_FUNC);
			append_int(script, decl->index);
		} break;
			
		case EXP_BOOL:
		{
			if(exp->boolean_value) append_code(script, OP_PUSH_TRUE);
			else append_code(script, OP_PUSH_FALSE);
		} break;
		
		case EXP_CHAR:
		{
			append_code(script, OP_PUSH_CHAR);
			append_int(script, exp->code);
		} break;
		
		case EXP_ARRAY_INDEX:
		{
			compile_value_expr(script, exp->array_index.index);
			compile_value_expr(script, exp->array_index.array);
			if(exp->array_index.array->tag->type == TAG_STRING)
				append_code(script, OP_STRING_GET);
			else
				append_code(script, OP_ARRAY_GET);
		} break;
		
		case EXP_ARRAY_LITERAL:
		{
			for(int i = 0; i < exp->array_literal.values.length; ++i)
			{
				expr_t* e = vec_get_value(&exp->array_literal.values, i, expr_t*);
				compile_value_expr(script, e);
			}
			append_code(script, OP_PUSH_ARRAY_BLOCK);
			append_int(script, (int)exp->array_literal.values.length);
		} break;
		
		case EXP_LEN:
		{
			compile_value_expr(script, exp->len);
			if(exp->len->tag->type == TAG_STRING) append_code(script, OP_STRING_LEN);
			else if(exp->len->tag->type == TAG_ARRAY) append_code(script, OP_ARRAY_LEN);
		} break;
		
		case EXP_VAR:
		{
			if(exp->varx.decl)
			{
				if(exp->varx.decl->parent)
					append_code(script, OP_GETLOCAL);
				else
					append_code(script, OP_GET);
					
				append_int(script, exp->varx.decl->index);
			}
			else
			{
				// NOTE: This assumes resolve_symbols checked for a function reference existing
				func_decl_t* decl = reference_function(script, exp->varx.name);
				
				// TODO: Switch here
				if(decl->type == DECL_FUNCTION) append_code(script, OP_PUSH_FUNC);
				else if (decl->type == DECL_EXTERN) append_code(script, OP_PUSH_EXTERN_FUNC);
				else error_exit_p("Invalid function declaration type\n");
				
				append_int(script, decl->index);
			}
		} break;
		
		case EXP_EXTERN:
		case EXP_EXTERN_LIST: break;
		
		case EXP_NUMBER:
		{
			append_code(script, OP_PUSH_NUMBER);
			append_int(script, exp->number_index);
		} break;
		
		case EXP_STRING:
		{
			append_code(script, OP_PUSH_STRING);
			append_int(script, exp->string_index);
		} break;
	
		case EXP_PAREN:
		{
			compile_value_expr(script, exp->paren);
		} break;
		
		case EXP_UNARY:
		{
			compile_value_expr(script, exp->unaryx.rhs);
			switch(exp->unaryx.op)
			{
				case TOK_MINUS: append_code(script, OP_NEG); break;
				case TOK_NOT: append_code(script, OP_NOT); break;
				// NOTE: perhaps error here
			}
		} break;
		
		case EXP_BINARY:
		{
			compile_value_expr(script, exp->binx.rhs);
			compile_value_expr(script, exp->binx.lhs);
			
			switch(exp->binx.op)
			{
				case TOK_PLUS: append_code(script, OP_ADD); break;
				case TOK_MINUS: append_code(script, OP_SUB); break;
				case TOK_MUL: append_code(script, OP_MUL); break;
				case TOK_DIV: append_code(script, OP_DIV); break;
				case TOK_MOD: append_code(script, OP_MOD); break;

				case TOK_LT: append_code(script, OP_LT); break;
				case TOK_GT: append_code(script, OP_GT); break;
				case TOK_LTE: append_code(script, OP_LTE); break;
				case TOK_GTE: append_code(script, OP_GTE); break;
				
				case TOK_LAND: append_code(script, OP_LAND); break;
				case TOK_LOR: append_code(script, OP_LOR); break;
				
				case TOK_EQUALS: append_code(script, OP_EQU); break;
				case TOK_NOTEQUAL: append_code(script, OP_EQU); append_code(script, OP_NOT); break;
				
				default: break;
			}
		} break;
		
		case EXP_CALL:
		{
			compile_call(script, exp);
			append_code(script, OP_PUSH_RETVAL);
			
			// NOTE: because branching
			compile_file_line_info(script, exp, 1);
		} break;
		
		default:
			error_exit_e(exp, "Non-value expression used in value context\n");
			break;
	}
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x90, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
xorl %edx, %edx
callq 0x10100
movq -0x10(%rbp), %rax
movl 0x28(%rax), %eax
movq %rax, -0x68(%rbp)
subq $0x18, %rax
ja 0x109a6
movq -0x68(%rbp), %rax
leaq 0x343a(%rip), %rcx      # 0x1365c
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x8(%rbp), %rdi
xorl %esi, %esi
callq 0x9480
jmp 0x109b8
movq -0x10(%rbp), %rax
movq 0x38(%rax), %rax
movq 0x70(%rax), %rdi
callq 0x3580
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rdi
movq -0x10(%rbp), %rax
movq 0x38(%rax), %rax
movq 0x70(%rax), %rdx
xorl %esi, %esi
callq 0x2100
movl $0x0, -0x1c(%rbp)
movq -0x10(%rbp), %rax
movq 0x50(%rax), %rax
subq $0x1, %rax
movl %eax, -0x20(%rbp)
cmpl $0x0, -0x20(%rbp)
jl 0x10352
movq -0x10(%rbp), %rdi
addq $0x38, %rdi
addq $0x8, %rdi
movslq -0x20(%rbp), %rsi
callq 0x11890
movq (%rax), %rax
movq %rax, -0x28(%rbp)
movq -0x10(%rbp), %rax
movq 0x38(%rax), %rdi
movq -0x28(%rbp), %rax
movq 0x38(%rax), %rax
movq 0x38(%rax), %rsi
callq 0xbad0
movl %eax, -0x2c(%rbp)
cmpl $0x0, -0x2c(%rbp)
jge 0x102ef
movq -0x28(%rbp), %rdi
movq -0x28(%rbp), %rax
movq 0x38(%rax), %rax
movq 0x38(%rax), %rdx
movq -0x10(%rbp), %rax
movq 0x38(%rax), %rax
movq 0x30(%rax), %rcx
leaq 0x537e(%rip), %rsi      # 0x15666
movb $0x0, %al
callq 0xba00
movq -0x18(%rbp), %rax
movslq -0x2c(%rbp), %rcx
movb $0x1, (%rax,%rcx)
movl -0x1c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1c(%rbp)
movq -0x8(%rbp), %rdi
movl $0x4, %esi
callq 0x9480
movq -0x8(%rbp), %rax
movq %rax, -0x70(%rbp)
movq -0x8(%rbp), %rdi
cvtsi2sdl -0x2c(%rbp), %xmm0
callq 0xa230
movq -0x70(%rbp), %rdi
movl %eax, %esi
callq 0x109d0
movq -0x8(%rbp), %rdi
movq -0x28(%rbp), %rax
movq 0x40(%rax), %rsi
callq 0x101e0
movl -0x20(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x20(%rbp)
jmp 0x1027d
movq -0x10(%rbp), %rax
movq 0x38(%rax), %rax
movq 0x70(%rax), %rax
subq $0x1, %rax
movl %eax, -0x30(%rbp)
cmpl $0x0, -0x30(%rbp)
jl 0x10400
movq -0x18(%rbp), %rax
movslq -0x30(%rbp), %rcx
cmpb $0x0, (%rax,%rcx)
jne 0x103f0
movq -0x10(%rbp), %rax
movq 0x38(%rax), %rdi
addq $0x28, %rdi
addq $0x38, %rdi
movslq -0x30(%rbp), %rsi
callq 0x11890
movq %rax, -0x38(%rbp)
movq -0x38(%rbp), %rax
cmpq $0x0, 0x18(%rax)
je 0x103ee
movq -0x8(%rbp), %rdi
movl $0x4, %esi
callq 0x9480
movq -0x8(%rbp), %rax
movq %rax, -0x78(%rbp)
movq -0x8(%rbp), %rdi
cvtsi2sdl -0x30(%rbp), %xmm0
callq 0xa230
movq -0x78(%rbp), %rdi
movl %eax, %esi
callq 0x109d0
movq -0x8(%rbp), %rdi
movq -0x38(%rbp), %rax
movq 0x18(%rax), %rsi
callq 0x101e0
movl -0x1c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1c(%rbp)
jmp 0x103f0
jmp 0x103f2
movl -0x30(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x30(%rbp)
jmp 0x10365
movq -0x8(%rbp), %rdi
movl $0xb, %esi
callq 0x9480
movq -0x10(%rbp), %rax
movq 0x38(%rax), %rax
cmpb $0x0, 0x28(%rax)
je 0x1042c
movq -0x8(%rbp), %rdi
movl $0x1, %esi
callq 0x109d0
jmp 0x10443
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rax
movq 0x38(%rax), %rax
movq 0x70(%rax), %rax
movl %eax, %esi
callq 0x109d0
movq -0x8(%rbp), %rdi
movl -0x1c(%rbp), %esi
callq 0x109d0
movq -0x18(%rbp), %rdi
callq 0x2030
jmp 0x109b8
movq -0x10(%rbp), %rax
movq 0x38(%rax), %rax
movq 0x30(%rax), %rdi
movq -0x10(%rbp), %rax
movq 0x40(%rax), %rsi
callq 0xbad0
movl %eax, -0x3c(%rbp)
cmpl $0x0, -0x3c(%rbp)
jge 0x104a9
movq -0x10(%rbp), %rdi
movq -0x10(%rbp), %rax
movq 0x40(%rax), %rdx
movq -0x10(%rbp), %rax
movq 0x38(%rax), %rax
movq 0x30(%rax), %rax
movq 0x30(%rax), %rcx
leaq 0x4484(%rip), %rsi      # 0x14926
movb $0x0, %al
callq 0xba00
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rax
movq 0x38(%rax), %rsi
callq 0x101e0
movq -0x8(%rbp), %rdi
movl $0x11, %esi
callq 0x9480
movq -0x8(%rbp), %rdi
movl -0x3c(%rbp), %esi
callq 0x109d0
jmp 0x109b8
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rax
movq 0x38(%rax), %rax
movq 0x30(%rax), %rax
movq 0x30(%rax), %rsi
movq -0x10(%rbp), %rax
movq 0x40(%rax), %rdx
callq 0xb8e0
movq %rax, -0x48(%rbp)
cmpq $0x0, -0x48(%rbp)
jne 0x1052f
movq -0x10(%rbp), %rdi
movq -0x10(%rbp), %rax
movq 0x38(%rax), %rax
movq 0x30(%rax), %rax
movq 0x30(%rax), %rdx
movq -0x10(%rbp), %rax
movq 0x40(%rax), %rcx
leaq 0x518b(%rip), %rsi      # 0x156b3
movb $0x0, %al
callq 0xba00
movq -0x8(%rbp), %rdi
movl $0x6, %esi
callq 0x9480
movq -0x8(%rbp), %rdi
movq -0x48(%rbp), %rax
movl 0x60(%rax), %esi
callq 0x109d0
jmp 0x109b8
movq -0x10(%rbp), %rax
cmpb $0x0, 0x38(%rax)
je 0x1056c
movq -0x8(%rbp), %rdi
movl $0x1, %esi
callq 0x9480
jmp 0x1057a
movq -0x8(%rbp), %rdi
movl $0x2, %esi
callq 0x9480
jmp 0x109b8
movq -0x8(%rbp), %rdi
movl $0x3, %esi
callq 0x9480
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rax
movsbl 0x38(%rax), %esi
callq 0x109d0
jmp 0x109b8
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rax
movq 0x40(%rax), %rsi
callq 0x101e0
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rax
movq 0x38(%rax), %rsi
callq 0x101e0
movq -0x10(%rbp), %rax
movq 0x38(%rax), %rax
movq 0x30(%rax), %rax
cmpl $0x5, 0x20(%rax)
jne 0x105e7
movq -0x8(%rbp), %rdi
movl $0xe, %esi
callq 0x9480
jmp 0x105f5
movq -0x8(%rbp), %rdi
movl $0xf, %esi
callq 0x9480
jmp 0x109b8
movl $0x0, -0x4c(%rbp)
movslq -0x4c(%rbp), %rax
movq -0x10(%rbp), %rcx
cmpq 0x50(%rcx), %rax
jae 0x10643
movq -0x10(%rbp), %rdi
addq $0x38, %rdi
addq $0x8, %rdi
movslq -0x4c(%rbp), %rsi
callq 0x11890
movq (%rax), %rax
movq %rax, -0x58(%rbp)
movq -0x8(%rbp), %rdi
movq -0x58(%rbp), %rsi
callq 0x101e0
movl -0x4c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x4c(%rbp)
jmp 0x10601
movq -0x8(%rbp), %rdi
movl $0x9, %esi
callq 0x9480
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rax
movq 0x50(%rax), %rax
movl %eax, %esi
callq 0x109d0
jmp 0x109b8
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rax
movq 0x38(%rax), %rsi
callq 0x101e0
movq -0x10(%rbp), %rax
movq 0x38(%rax), %rax
movq 0x30(%rax), %rax
cmpl $0x5, 0x20(%rax)
jne 0x1069c
movq -0x8(%rbp), %rdi
movl $0xc, %esi
callq 0x9480
jmp 0x106be
movq -0x10(%rbp), %rax
movq 0x38(%rax), %rax
movq 0x30(%rax), %rax
cmpl $0x7, 0x20(%rax)
jne 0x106bc
movq -0x8(%rbp), %rdi
movl $0xd, %esi
callq 0x9480
jmp 0x106be
jmp 0x109b8
movq -0x10(%rbp), %rax
cmpq $0x0, 0x40(%rax)
je 0x10710
movq -0x10(%rbp), %rax
movq 0x40(%rax), %rax
cmpq $0x0, (%rax)
je 0x106ec
movq -0x8(%rbp), %rdi
movl $0x28, %esi
callq 0x9480
jmp 0x106fa
movq -0x8(%rbp), %rdi
movl $0x26, %esi
callq 0x9480
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rax
movq 0x40(%rax), %rax
movl 0x1c(%rax), %esi
callq 0x109d0
jmp 0x10779
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rax
movq 0x38(%rax), %rsi
callq 0x9cb0
movq %rax, -0x60(%rbp)
movq -0x60(%rbp), %rax
cmpl $0x0, 0x8(%rax)
jne 0x1073f
movq -0x8(%rbp), %rdi
movl $0x6, %esi
callq 0x9480
jmp 0x10769
movq -0x60(%rbp), %rax
cmpl $0x1, 0x8(%rax)
jne 0x10759
movq -0x8(%rbp), %rdi
movl $0x7, %esi
callq 0x9480
jmp 0x10767
leaq 0x4f83(%rip), %rdi      # 0x156e3
movb $0x0, %al
callq 0xa0e0
jmp 0x10769
movq -0x8(%rbp), %rdi
movq -0x60(%rbp), %rax
movl 0x60(%rax), %esi
callq 0x109d0
jmp 0x109b8
jmp 0x109b8
movq -0x8(%rbp), %rdi
movl $0x4, %esi
callq 0x9480
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rax
movl 0x38(%rax), %esi
callq 0x109d0
jmp 0x109b8
movq -0x8(%rbp), %rdi
movl $0x5, %esi
callq 0x9480
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rax
movl 0x38(%rax), %esi
callq 0x109d0
jmp 0x109b8
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rax
movq 0x38(%rax), %rsi
callq 0x101e0
jmp 0x109b8
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rax
movq 0x38(%rax), %rsi
callq 0x101e0
movq -0x10(%rbp), %rax
movl 0x40(%rax), %eax
movl %eax, -0x7c(%rbp)
subl $0x23, %eax
je 0x1081b
jmp 0x10801
movl -0x7c(%rbp), %eax
subl $0x26, %eax
jne 0x10829
jmp 0x1080b
movq -0x8(%rbp), %rdi
movl $0x1e, %esi
callq 0x9480
jmp 0x10829
movq -0x8(%rbp), %rdi
movl $0x1f, %esi
callq 0x9480
jmp 0x109b8
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rax
movq 0x40(%rax), %rsi
callq 0x101e0
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rax
movq 0x38(%rax), %rsi
callq 0x101e0
movq -0x10(%rbp), %rax
movl 0x48(%rax), %eax
addl $-0x25, %eax
movl %eax, %ecx
movq %rcx, -0x88(%rbp)
subl $0xc, %eax
ja 0x10973
movq -0x88(%rbp), %rax
leaq 0x2e46(%rip), %rcx      # 0x136c0
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x8(%rbp), %rdi
movl $0x13, %esi
callq 0x9480
jmp 0x10975
movq -0x8(%rbp), %rdi
movl $0x14, %esi
callq 0x9480
jmp 0x10975
movq -0x8(%rbp), %rdi
movl $0x15, %esi
callq 0x9480
jmp 0x10975
movq -0x8(%rbp), %rdi
movl $0x16, %esi
callq 0x9480
jmp 0x10975
movq -0x8(%rbp), %rdi
movl $0x17, %esi
callq 0x9480
jmp 0x10975
movq -0x8(%rbp), %rdi
movl $0x18, %esi
callq 0x9480
jmp 0x10975
movq -0x8(%rbp), %rdi
movl $0x19, %esi
callq 0x9480
jmp 0x10975
movq -0x8(%rbp), %rdi
movl $0x1a, %esi
callq 0x9480
jmp 0x10975
movq -0x8(%rbp), %rdi
movl $0x1b, %esi
callq 0x9480
jmp 0x10975
movq -0x8(%rbp), %rdi
movl $0x1c, %esi
callq 0x9480
jmp 0x10975
movq -0x8(%rbp), %rdi
movl $0x1d, %esi
callq 0x9480
jmp 0x10975
movq -0x8(%rbp), %rdi
movl $0x20, %esi
callq 0x9480
jmp 0x10975
movq -0x8(%rbp), %rdi
movl $0x20, %esi
callq 0x9480
movq -0x8(%rbp), %rdi
movl $0x1f, %esi
callq 0x9480
jmp 0x10975
jmp 0x10975
jmp 0x109b8
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
callq 0x10c10
movq -0x8(%rbp), %rdi
movl $0xa, %esi
callq 0x9480
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movl $0x1, %edx
callq 0x10100
jmp 0x109b8
movq -0x10(%rbp), %rdi
leaq 0x4d55(%rip), %rsi      # 0x15706
movb $0x0, %al
callq 0xba00
addq $0x90, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)