Exemple #1
0
static void gen_modify( qli_nod* node) //, qli_req* org_request)
{
/**************************************
 *
 *	g e n _ m o d i f y
 *
 **************************************
 *
 * Functional description
 *	Generate a MODIFY statement.
 *
 **************************************/
	qli_req* request = (qli_req*) node->nod_arg[e_mod_request];

	qli_rlb* rlb = CHECK_RLB(request->req_blr);

	if (node->nod_arg[e_mod_send])
		gen_send_receive((qli_msg*) node->nod_arg[e_mod_send], blr_receive);

	qli_nod** ptr = &node->nod_arg[e_mod_count];
	for (const qli_nod* const* const end = ptr + node->nod_count; ptr < end; ptr++)
	{
		qli_ctx* context = (qli_ctx*) *ptr;
		STUFF(blr_modify);
		STUFF(context->ctx_source->ctx_context);
		STUFF(context->ctx_context);
	}
	STUFF(blr_begin);
	gen_statement(node->nod_arg[e_mod_statement], request);
	STUFF(blr_end);
}
Exemple #2
0
static void gen_if( qli_nod* node, qli_req* request)
{
/**************************************
 *
 *	g e n _ i f
 *
 **************************************
 *
 * Functional description
 *	Generate code for an IF statement.  Depending
 *	on the environment, this may be either a QLI
 *	context IF or a database context IF.
 *
 **************************************/

	// If the statement is local to QLI, force the sub- statements/expressions to be local also.
	// If not local, generate BLR.

	if (node->nod_flags & NOD_local)
	{
		gen_expression(node->nod_arg[e_if_boolean], 0);
		gen_statement(node->nod_arg[e_if_true], request);
		if (node->nod_arg[e_if_false])
			gen_statement(node->nod_arg[e_if_false], request);
	}
	else
	{
	    // probably the var is irrelevant, but not the function call,
	    // as it makes sure there's enough room.
		qli_rlb* rlb = CHECK_RLB(request->req_blr);
		STUFF(blr_if);
		gen_expression(node->nod_arg[e_if_boolean], request);
		STUFF(blr_begin);
		gen_statement(node->nod_arg[e_if_true], request);
		STUFF(blr_end);
		if (node->nod_arg[e_if_false])
		{
			STUFF(blr_begin);
			gen_statement(node->nod_arg[e_if_false], request);
			STUFF(blr_end);
		}
		else
			STUFF(blr_end);
	}
}
Exemple #3
0
static void gen_functions(ArrayList *statements) {
  int i;
  for (i = 0; i < statements->length; i++) {
    ClmStmtNode *node = statements->data[i];
    if (node->type == STMT_TYPE_FUNC_DEC) {
      gen_statement(node);
    }
  }
}
Exemple #4
0
static void gen_store( qli_nod* node, qli_req* request)
{
/**************************************
 *
 *	g e n _ s t o r e
 *
 **************************************
 *
 * Functional description
 *	Generate code for STORE statement.
 *
 **************************************/

	// If there is a request associated with the statement, prepare to
	// generate BLR.  Otherwise assume that a request is alrealdy initialized.

	if (node->nod_arg[e_sto_request])
	{
		request = (qli_req*) node->nod_arg[e_sto_request];
		gen_request(request);
	}

	qli_rlb* rlb = CHECK_RLB(request->req_blr);

	// If there is a message to be sent, build a receive for it

	if (node->nod_arg[e_sto_send])
		gen_send_receive((qli_msg*) node->nod_arg[e_sto_send], blr_receive);

	// Generate the STORE statement proper.

	STUFF(blr_store);
	qli_ctx* context = (qli_ctx*) node->nod_arg[e_sto_context];
	qli_rel* relation = context->ctx_relation;
	STUFF(blr_rid);
	STUFF_WORD(relation->rel_id);
	STUFF(context->ctx_context);

	// Build  the body of the loop.

	STUFF(blr_begin);
	gen_statement(node->nod_arg[e_sto_statement], request);
	STUFF(blr_end);

	// If this is our request, compile it.

	if (node->nod_arg[e_sto_request])
		gen_compile(request);
}
Exemple #5
0
qli_nod* GEN_generate( qli_nod* node)
{
/**************************************
 *
 *	G E N _ g e n e r a t e
 *
 **************************************
 *
 * Functional description
 *	Generate and compile BLR.
 *
 **************************************/

	gen_statement(node, 0);

	return node;
}
Exemple #6
0
void gen_statement(tree_t *t) {
  int local_if_label;
  int local_while_label;
  int local_for_label;
  int num_args;

  if (t->type == ARRAY || t->right->type == ARRAY || t->left->type == ARRAY) {
    yyerror("Array access not supported");
  }

  switch(t->type) {
  case ASSIGNOP:
    // Generate code for expression
    gen_label(t->right, 1);
    gen_expression(t->right);
    fprintf(yyout, "\tmovl\t%%ebx, %%eax\n");
    
    // If this is actually a return statement, then return with correct value in %eax
    if(!strcmp(t->left->attribute.variable->name, top_scope->curr->name)) 
      fprintf(yyout, "\tjmp\tsubprog%send\n", top_scope->curr->name);
    else {
      // Generate code for assignment
      gen_assignment(t->left);
    }

    break;
  case IF:
    local_if_label = if_label++;
    
    //Generate code for expression
    gen_label(t->left, 1);
    gen_expression(t->left);

    //Compare and jump accordingly
    fprintf(yyout, "\tcmpl\t$1, %%ebx\n\tjge\tiftrue%d\n", local_if_label);

    //Generate code for else first
    if (t->right->right != NULL) {
      gen_statement(t->right->right);
      fprintf(yyout, "\tjmp\tifend%d\n", local_if_label);
    }
    
    //Generate code for true section
    fprintf(yyout, "iftrue%d:\n", local_if_label);
    gen_statement(t->right->left);
    fprintf(yyout, "ifend%d:\n", local_if_label);

    break;
  case WHILE:
    local_while_label = while_label++;

    //Plant label for beginning of loop
    fprintf(yyout, "beginwhile%d:\n", local_while_label);
    
    //Generate code for expression
    gen_label(t->left, 1);
    gen_expression(t->left);

    //Compare and jump to end if needed
    fprintf(yyout, "\tcmpl\t$0, %%ebx\n\tje\tendwhile%d\n", local_while_label);

    //Generate code for statements
    gen_statement(t->right);
    fprintf(yyout, "\tjmp\tbeginwhile%d\n", local_while_label);
    fprintf(yyout, "endwhile%d:\n", local_while_label);

    break;
  case PROCEDURE:
    if (!strcmp(t->left->attribute.variable->name, "read"))
      gen_read(t->right);
    else if (!strcmp(t->left->attribute.variable->name, "write"))
      gen_write(t->right);
    else if (t->right != NULL) {
      // push arguments on the stack
      num_args = gen_expression_list(t->right); 
      fprintf(yyout, "\tcall\tsubprog%s\n", t->left->attribute.variable->name);

      // move the top of the stack below args
      fprintf(yyout, "\taddl\t$%d, %%esp\n", 4*num_args); 
    }
    else {
      fprintf(yyout, "\tcall\tsubprog%s\n", t->left->attribute.variable->name);
    }
    
    break;
  case COMMA:
    // Generate left and right statements
    if (t->left->type == ARRAY || t->right->type == ARRAY)
      yyerror("Array access not supported");
    else {
      gen_statement(t->left);
      gen_statement(t->right);
    }
    break;
  case FOR:
    local_for_label = for_label++;

    // Generate assignment
    gen_statement(t->left->left);

    //Plant label for beginning
    fprintf(yyout, "forloop%d:\n", local_for_label);

    // Generate expression for TO value
    gen_label(t->left->right, 1);
    gen_expression(t->left->right);

    //Compare and jump to end if needed
    if (t->left->left->left->attribute.variable->local_or_parameter == LOCAL)
      fprintf(yyout, "\tcmpl\t-%i(%%ebp), %%ebx\n\tjl\tforend%d\n",
	      t->left->left->left->attribute.variable->offset, local_for_label);
    else
      fprintf(yyout, "\tcmpl\t-%i(%%ebp), %%ebx\n\tjl\tforend%d\n",
	      t->left->left->left->attribute.variable->offset, local_for_label); 

    //Generate code for statements
    gen_statement(t->right);

    //Increment, jump to top then plant end label
    fprintf(yyout, "\tincl\t-%i(%%ebp)\n\tjmp\tforloop%d\nforend%d:\n", 
	    t->left->left->left->attribute.variable->offset,
	    local_for_label, local_for_label);

    break;
  default:
    fprintf(stderr, "TYPE: %d\n", t->type);
    yywarn("Statement not supported");
    break;
  }
}
Exemple #7
0
static void gen_statement( qli_nod* node, qli_req* request)
{
/**************************************
 *
 *	g e n _ s t a t e m e n t
 *
 **************************************
 *
 * Functional description
 *	Generate BLR for statement.
 *
 **************************************/
	if (request)
		CHECK_RLB(request->req_blr);

	switch (node->nod_type)
	{
	case nod_abort:
		if (node->nod_count)
			gen_expression(node->nod_arg[0], 0);
		return;

	case nod_assign:
		gen_assignment(node, request);
		return;

	case nod_commit_retaining:
		return;

	case nod_erase:
		gen_erase(node, request);
		return;

	case nod_for:
	case nod_report_loop:
		gen_for(node, request);
		return;

	case nod_list:
	    {
	        qli_nod** ptr = node->nod_arg;
			for (const qli_nod* const* const end = ptr + node->nod_count; ptr < end; ++ptr)
			{
				gen_statement(*ptr, request);
			}
			return;
		}

	case nod_modify:
		gen_modify(node); //, request);
		return;

	case nod_output:
		gen_statement(node->nod_arg[e_out_statement], request);
		return;

	case nod_print:
		gen_print_list(node->nod_arg[e_prt_list], request);
		return;

	case nod_repeat:
		gen_statement(node->nod_arg[e_rpt_statement], request);
		return;

	case nod_report:
		gen_report(node, request);
		return;

	case nod_store:
		gen_store(node, request);
		return;

	case nod_if:
		gen_if(node, request);
		return;

	default:
		ERRQ_bugcheck(354);			// Msg354 gen_statement: not yet implemented
	}
}
Exemple #8
0
static void gen_for( qli_nod* node, qli_req* request)
{
/**************************************
 *
 *	g e n _ f o r
 *
 **************************************
 *
 * Functional description
 *	Generate BLR for a FOR loop, included synchronization messages.
 *
 **************************************/

	// If there is a request associated with the statement, prepare to
	// generate BLR.  Otherwise assume that a request is alrealdy initialized.

	if (node->nod_arg[e_for_request])
	{
		request = (qli_req*) node->nod_arg[e_for_request];
		gen_request(request);
	}

	qli_rlb* rlb = CHECK_RLB(request->req_blr);

	// If the statement requires an end of file marker, build a BEGIN/END around
	// the whole statement.

	const qli_msg* message = (qli_msg*) node->nod_arg[e_for_receive];
	if (message)
		STUFF(blr_begin);

	// If there is a message to be sent, build a receive for it

	if (node->nod_arg[e_for_send])
		gen_send_receive((qli_msg*) node->nod_arg[e_for_send], blr_receive);

	// Generate the FOR loop proper.

	STUFF(blr_for);
	gen_rse(node->nod_arg[e_for_rse], request);
	STUFF(blr_begin);

	// If data is to be received (included EOF), build a send

	const qli_par* eof = 0;
	dsc desc;
	USHORT value;

	if (message)
	{
		gen_send_receive(message, blr_send);
		STUFF(blr_begin);

		// Build assigments for all values referenced.

		for (const qli_par* parameter = message->msg_parameters; parameter;
			parameter = parameter->par_next)
		{
			if (parameter->par_value)
			{
				STUFF(blr_assignment);
				gen_expression(parameter->par_value, request);
				gen_parameter(parameter, request);
			}
		}

		// Next, make a FALSE for the end of file parameter

		eof = (qli_par*) node->nod_arg[e_for_eof];
		desc.dsc_dtype = dtype_short;
		desc.dsc_length = sizeof(SSHORT);
		desc.dsc_scale = 0;
		desc.dsc_sub_type = 0;
		desc.dsc_address = (UCHAR*) &value;
		QLI_validate_desc(desc);

		STUFF(blr_assignment);
		value = FALSE;
		gen_literal(&desc, request);
		gen_parameter(eof, request);

		STUFF(blr_end);
	}

	// Build  the body of the loop.

	const qli_msg* continuation = request->req_continue;
	if (continuation)
	{
		STUFF(blr_label);
		const USHORT label = request->req_label++;
		STUFF(label);
		STUFF(blr_loop);
		STUFF(blr_select);
		gen_send_receive(continuation, blr_receive);
		STUFF(blr_leave);
		STUFF(label);
	}

	qli_nod* sub = node->nod_arg[e_for_statement];
	gen_statement(sub, request);

	STUFF(blr_end);

	if (continuation)
		STUFF(blr_end);

	// Finish off by building a SEND to indicate end of file

	if (message)
	{
		gen_send_receive(message, blr_send);
		STUFF(blr_assignment);
		value = TRUE;
		gen_literal(&desc, request);
		gen_parameter(eof, request);
		STUFF(blr_end);
	}

	// If this is our request, compile it.

	if (node->nod_arg[e_for_request])
		gen_compile(request);
}