Exemple #1
0
Fichier : do.c Projet : franred/ofc
static ofc_sema_stmt_t* ofc_sema_stmt_do_while__label(
	ofc_sema_scope_t* scope,
	const ofc_parse_stmt_t* stmt)
{

	if (!stmt
		|| (stmt->type != OFC_PARSE_STMT_DO_WHILE)
		|| !stmt->do_while_block.cond)
		return NULL;

	ofc_sema_stmt_t s;
	s.type = OFC_SEMA_STMT_DO_WHILE;

	s.do_while.end_label = ofc_sema_expr(
	scope, stmt->do_while.end_label);
	if (!s.do_while.end_label)
		return NULL;

	s.do_while.cond = ofc_sema_expr(
		scope, stmt->do_while.cond);
	if (!s.do_while.cond)
		return NULL;

	const ofc_sema_type_t* type
		= ofc_sema_expr_type(s.do_while.cond);
	if (!ofc_sema_type_is_logical(type))
	{
		ofc_sparse_ref_error(stmt->do_while.cond->src,
			"IF condition type must be LOGICAL.");

		ofc_sema_expr_delete(s.do_while.cond);
		return NULL;
	}

	ofc_sema_stmt_t* as = ofc_sema_stmt_alloc(s);
	if (!as)
	{
		ofc_sema_expr_delete(s.do_while.cond);
		return NULL;
	}

	return as;
}
Exemple #2
0
Fichier : do.c Projet : franred/ofc
static ofc_sema_stmt_t* ofc_sema_stmt_do__label(
	ofc_sema_scope_t* scope,
	const ofc_parse_stmt_t* stmt)
{
	if (!stmt
		|| (stmt->type != OFC_PARSE_STMT_DO_LABEL)
		|| !stmt->do_label.init
		|| !stmt->do_label.last
		|| !stmt->do_label.end_label)
		return NULL;

	ofc_sema_stmt_t s;
	s.type = OFC_SEMA_STMT_DO_LABEL;
	s.do_label.iter = NULL;
	s.do_label.init = NULL;
	s.do_label.last = NULL;
	s.do_label.step = NULL;

	s.do_label.end_label = ofc_sema_expr(
		scope, stmt->do_label.end_label);
	if (!s.do_label.end_label)
		return NULL;

	if (!ofc_sema_stmt__loop_control(
		scope, stmt->do_label.init,
		stmt->do_label.last, stmt->do_label.step,
		&s.do_label.iter, &s.do_label.init,
		&s.do_label.last, &s.do_label.step))
	{
		ofc_sema_expr_delete(s.do_label.end_label);
		return NULL;
	}

	ofc_sema_stmt_t* as = ofc_sema_stmt_alloc(s);
	if (!as)
	{
		ofc_sema_expr_delete(s.do_label.end_label);
		ofc_sema_expr_delete(s.do_label.init);
		ofc_sema_expr_delete(s.do_label.last);
		ofc_sema_expr_delete(s.do_label.step);
		return NULL;
	}

	return as;
}
Exemple #3
0
ofc_sema_stmt_t* ofc_sema_stmt_io_read(
	ofc_sema_scope_t* scope,
	const ofc_parse_stmt_t* stmt)
{
	if (!scope || !stmt
		|| (stmt->type != OFC_PARSE_STMT_IO_READ)
		|| !stmt->io_read.params)
		return NULL;

	ofc_sema_stmt_t s;
	s.type = OFC_SEMA_STMT_IO_READ;
	s.io_read.unit         = NULL;
	s.io_read.stdin        = false;
	s.io_read.format       = NULL;
	s.io_read.format_ldio  = false;
	s.io_read.formatted    = false;
	s.io_read.iostat       = NULL;
	s.io_read.rec          = NULL;
	s.io_read.err          = NULL;
	s.io_read.iolist       = NULL;
	s.io_read.advance      = NULL;
	s.io_read.end          = NULL;
	s.io_read.eor          = NULL;
	s.io_read.size         = NULL;

	ofc_parse_call_arg_t* ca_unit    = NULL;
	ofc_parse_call_arg_t* ca_format  = NULL;
	ofc_parse_call_arg_t* ca_iostat  = NULL;
	ofc_parse_call_arg_t* ca_rec     = NULL;
	ofc_parse_call_arg_t* ca_err     = NULL;
	ofc_parse_call_arg_t* ca_advance = NULL;
	ofc_parse_call_arg_t* ca_end     = NULL;
	ofc_parse_call_arg_t* ca_eor     = NULL;
	ofc_parse_call_arg_t* ca_size    = NULL;

	if (stmt->io_read.has_brakets)
	{
		unsigned i;
		for (i = 0; i < stmt->io_read.params->count; i++)
		{
			ofc_parse_call_arg_t* param
				= stmt->io_read.params->call_arg[i];
			if (!param) continue;

			if (ofc_sparse_ref_empty(param->name))
			{
				if (i >= 2)
				{
					ofc_sparse_ref_error(param->src,
						"Un-named parameter %u has no meaning in READ.", i);
					return NULL;
				}

				if (i == 0)
				{
					ca_unit = param;
				}
				else
				{
					if (!ca_unit)
					{
						ofc_sparse_ref_error(param->src,
							"Un-named format parameter only valid after UNIT in READ.");
						return NULL;
					}

					ca_format = param;
				}
			}
			else if (ofc_str_ref_equal_strz_ci(param->name.string, "UNIT"))
			{
				if (ca_unit)
				{
					ofc_sparse_ref_error(param->src,
						"Re-definition of UNIT in READ.");
					return NULL;
				}

				ca_unit = param;
			}
			else if (ofc_str_ref_equal_strz_ci(param->name.string, "FMT"))
			{
				if (ca_format)
				{
					ofc_sparse_ref_error(param->src,
						"Re-definition of FMT in READ.");
					return NULL;
				}

				ca_format = param;
			}
			else if (ofc_str_ref_equal_strz_ci(param->name.string, "IOSTAT"))
			{
				if (ca_iostat)
				{
					ofc_sparse_ref_error(param->src,
						"Re-definition of IOSTAT in READ.");
					return NULL;
				}

				ca_iostat = param;
			}
			else if (ofc_str_ref_equal_strz_ci(param->name.string, "REC"))
			{
				if (ca_rec)
				{
					ofc_sparse_ref_error(param->src,
						"Re-definition of REC in READ.");
					return NULL;
				}

				ca_rec = param;
			}
			else if (ofc_str_ref_equal_strz_ci(param->name.string, "ERR"))
			{
				if (ca_err)
				{
					ofc_sparse_ref_error(param->src,
						"Re-definition of ERR in READ.");
					return NULL;
				}

				ca_err = param;
			}
			else if (ofc_str_ref_equal_strz_ci(param->name.string, "ADVANCE"))
			{
				if (ca_advance)
				{
					ofc_sparse_ref_error(param->src,
						"Re-definition of ADVANCE in READ.");
					return NULL;
				}

				ca_advance = param;
			}
			else if (ofc_str_ref_equal_strz_ci(param->name.string, "END"))
			{
				if (ca_end)
				{
					ofc_sparse_ref_error(param->src,
						"Re-definition of END in READ.");
					return NULL;
				}

				ca_end = param;
			}
			else if (ofc_str_ref_equal_strz_ci(param->name.string, "SIZE"))
			{
				if (ca_size)
				{
					ofc_sparse_ref_error(param->src,
						"Re-definition of SIZE in READ.");
					return NULL;
				}

				ca_size = param;
			}
			else
			{
				ofc_sparse_ref_error(param->src,
					"Unrecognized paramater %u name '%.*s' in READ.",
					i, param->name.string.size, param->name.string.base);
				return NULL;
			}
		}

		if (!ca_unit)
		{
			ofc_sparse_ref_error(stmt->src,
				"No UNIT defined in READ.");
			return NULL;
		}
	}
	else
	{
		ca_format = stmt->io_read.params->call_arg[0];
	}

	if (ca_unit && (ca_unit->type == OFC_PARSE_CALL_ARG_ASTERISK))
	{
		s.io_read.stdin = true;
	}
	else if (ca_unit && (ca_unit->type == OFC_PARSE_CALL_ARG_EXPR))
	{
		s.io_read.unit = ofc_sema_expr(
			scope, ca_unit->expr);
		if (!s.io_read.unit) return NULL;

		const ofc_sema_type_t* etype
			= ofc_sema_expr_type(s.io_read.unit);
		if (!etype)
		{
			ofc_sema_stmt_io_read__cleanup(s);
			return NULL;
		}

		if (!ofc_sema_type_is_character(etype)
			&& (!ofc_sema_type_is_integer(etype)
				|| !ofc_sema_expr_validate_uint(s.io_read.unit)))
		{
			ofc_sparse_ref_error(stmt->src,
				   "UNIT must be a positive INTEGER "
				   "or a CHARACTER expression in READ");
			ofc_sema_stmt_io_read__cleanup(s);
			return NULL;
		}
	}
	else if (ca_unit)
	{
		ofc_sparse_ref_error(stmt->src,
			"UNIT must be an INTEGER or CHARACTER "
			"expression, or asterisk in READ");
		return NULL;
	}
	else
	{
		s.io_read.stdin = true;
	}

	if (ca_format && (ca_format->type == OFC_PARSE_CALL_ARG_ASTERISK))
	{
		s.io_read.format_ldio = true;
		s.io_read.formatted   = true;
	}
	else if (ca_format && (ca_format->type == OFC_PARSE_CALL_ARG_EXPR))
	{
		s.io_read.formatted   = true;

		s.io_read.format = ofc_sema_expr(
			scope, ca_format->expr);
		if (!s.io_read.format)
		{
			ofc_sema_stmt_io_read__cleanup(s);
			return NULL;
		}

		const ofc_sema_type_t* etype
			= ofc_sema_expr_type(s.io_read.format);
		if (!etype)
		{
			ofc_sema_stmt_io_read__cleanup(s);
			return NULL;
		}

		if (ofc_sema_type_is_integer(etype))
		{
			s.io_read.format->is_label  = true;
			s.io_read.format->is_format = true;
		}
		else if (etype->type != OFC_SEMA_TYPE_CHARACTER)
		{
			/* TODO - Support INTEGER array formats. */

			ofc_sparse_ref_error(stmt->src,
				"Format (FMT) must be a label or character string in READ");
			ofc_sema_stmt_io_read__cleanup(s);
			return NULL;
		}
	}
	else if (ca_format)
	{
		ofc_sparse_ref_error(stmt->src,
			"Format (FMT) must be an INTEGER expression or asterisk in READ");
		ofc_sema_stmt_io_read__cleanup(s);
		return NULL;
	}

	bool is_nonadvance = false;
	if (ca_advance && s.io_read.stdin)
	{
		ofc_sparse_ref_error(stmt->src,
			"ADVANCE specifier can only be used with an external UNIT in READ");
		ofc_sema_stmt_io_read__cleanup(s);
		return NULL;
	}
	else if (ca_advance && (!ca_format || s.io_read.format_ldio))
	{
		ofc_sparse_ref_error(stmt->src,
			"ADVANCE specifier can only be used with a formatted input in READ");
		ofc_sema_stmt_io_read__cleanup(s);
		return NULL;
	}
	else if (ca_advance)
	{
		s.io_read.advance = ofc_sema_expr(
			scope, ca_advance->expr);
		if (!s.io_read.advance)
		{
			ofc_sema_stmt_io_read__cleanup(s);
			return NULL;
		}

		const ofc_sema_type_t* etype
			= ofc_sema_expr_type(s.io_read.advance);
		if (!etype)
		{
			ofc_sema_stmt_io_read__cleanup(s);
			return NULL;
		}

		if (etype->type != OFC_SEMA_TYPE_CHARACTER)
		{
			ofc_sparse_ref_error(stmt->src,
				"ADVANCE must be a CHARACTER expression in READ");
			ofc_sema_stmt_io_read__cleanup(s);
			return NULL;
		}
		else
		{
			const ofc_sema_typeval_t* constant
				= ofc_sema_expr_constant(s.io_read.advance);

			is_nonadvance = (constant
				&& ofc_typeval_character_equal_strz_ci(constant, "NO"));
			if (constant && !is_nonadvance
				&& !ofc_typeval_character_equal_strz_ci(constant, "YES"))
			{
				ofc_sparse_ref_error(stmt->src,
					"ADVANCE must be YES/NO in WRITE");
				ofc_sema_stmt_io_read__cleanup(s);
				return NULL;
			}
		}
	}

	if (ca_end)
	{
		s.io_read.end = ofc_sema_expr_label(
			scope, ca_end->expr);
		if (!s.io_read.end)
		{
			ofc_sema_stmt_io_read__cleanup(s);
			return NULL;
		}
	}

	if (ca_eor)
	{
		s.io_read.eor = ofc_sema_expr_label(
			scope, ca_eor->expr);
		if (!s.io_read.eor)
		{
			ofc_sema_stmt_io_read__cleanup(s);
			return NULL;
		}
	}

	if (ca_err)
	{
		s.io_read.err = ofc_sema_expr_label(
			scope, ca_err->expr);
		if (!s.io_read.err)
		{
			ofc_sema_stmt_io_read__cleanup(s);
			return NULL;
		}
	}

	if (ca_iostat)
	{
		s.io_read.iostat = ofc_sema_expr(
			scope, ca_iostat->expr);
		if (!s.io_read.iostat)
		{
			ofc_sema_stmt_io_read__cleanup(s);
			return NULL;
		}

		if (s.io_read.iostat->type != OFC_SEMA_EXPR_LHS)
		{
			ofc_sparse_ref_error(stmt->src,
				"IOSTAT must be a variable in READ");
			ofc_sema_stmt_io_read__cleanup(s);
			return NULL;
		}

		const ofc_sema_type_t* etype
			= ofc_sema_expr_type(s.io_read.iostat);
		if (!etype)
		{
			ofc_sema_stmt_io_read__cleanup(s);
			return NULL;
		}

		if (!ofc_sema_type_is_integer(etype))
		{
			ofc_sparse_ref_error(stmt->src,
				"IOSTAT must be of type INTEGER in READ");
			ofc_sema_stmt_io_read__cleanup(s);
			return NULL;
		}
	}

	if (ca_rec && (s.io_read.format_ldio || ca_end))
	{
		ofc_sparse_ref_error(stmt->src,
			"REC specifier not compatible with END,"
			" NML or list-directed data transfer in READ");
		ofc_sema_stmt_io_read__cleanup(s);
		return NULL;
	}
	else if (ca_rec)
	{
		s.io_read.rec = ofc_sema_expr(
			scope, ca_rec->expr);
		if (!s.io_read.rec)
		{
			ofc_sema_stmt_io_read__cleanup(s);
			return NULL;
		}

		const ofc_sema_type_t* etype
			= ofc_sema_expr_type(s.io_read.rec);
		if (!etype)
		{
			ofc_sema_stmt_io_read__cleanup(s);
			return NULL;
		}

		if (!ofc_sema_type_is_integer(etype))
		{
			ofc_sparse_ref_error(stmt->src,
				"REC must be of type INTEGER in READ");
			ofc_sema_stmt_io_read__cleanup(s);
			return NULL;
		}
	}

	if (ca_size && !is_nonadvance)
	{
		ofc_sparse_ref_error(stmt->src,
			"SIZE not compatible with advancing formatted "
			"sequential data transfer in READ");
		ofc_sema_stmt_io_read__cleanup(s);
		return NULL;
	}
	else if (ca_size)
	{
		if (s.io_read.size->type != OFC_SEMA_EXPR_LHS)
		{
			ofc_sparse_ref_error(stmt->src,
				"SIZE must be a variable in READ");
			ofc_sema_stmt_io_read__cleanup(s);
			return NULL;
		}
		/* TODO - The variable specified in SIZE must
				  not be the same as or associated with any
				  entity in the input/output item list or in
				  the namelist group or with the variable
				  specified in the IOSTAT= specifier */
		const ofc_sema_type_t* etype
			= ofc_sema_expr_type(s.io_read.size);
		if (!etype)
		{
			ofc_sema_stmt_io_read__cleanup(s);
			return NULL;
		}

		if (!ofc_sema_type_is_integer(etype))
		{
			ofc_sparse_ref_error(stmt->src,
				"SIZE must be of type INTEGER in READ");
			ofc_sema_stmt_io_read__cleanup(s);
			return NULL;
		}
	}

	/* Check iolist */
	if (stmt->io_read.iolist)
	{
		s.io_read.iolist
			= ofc_sema_lhs_list_id(
				scope, stmt->io_read.iolist);
		if (!s.io_read.iolist
			|| !ofc_sema_lhs_list_mark_used(
				s.io_read.iolist, true, false))
		{
			ofc_sema_stmt_io_read__cleanup(s);
			return NULL;
		}
	}

	ofc_sema_stmt_t* as
		= ofc_sema_stmt_alloc(s);
	if (!as)
	{
		ofc_sema_stmt_io_read__cleanup(s);
		return NULL;
	}
	return as;
}
Exemple #4
0
ofc_sema_stmt_t* ofc_sema_stmt_io_inquire(
	ofc_sema_scope_t* scope,
	const ofc_parse_stmt_t* stmt)
{
	if (!scope || !stmt
		|| (stmt->type != OFC_PARSE_STMT_IO_INQUIRE)
		|| !stmt->io.params)
		return NULL;

	ofc_sema_stmt_t s;
	s.type = OFC_SEMA_STMT_IO_INQUIRE;
	s.io_inquire.unit          = NULL;
	s.io_inquire.access        = NULL;
	s.io_inquire.action        = NULL;
	s.io_inquire.blank         = NULL;
	s.io_inquire.delim         = NULL;
	s.io_inquire.direct        = NULL;
	s.io_inquire.err           = NULL;
	s.io_inquire.exist         = NULL;
	s.io_inquire.file          = NULL;
	s.io_inquire.form          = NULL;
	s.io_inquire.formatted     = NULL;
	s.io_inquire.iostat        = NULL;
	s.io_inquire.name          = NULL;
	s.io_inquire.named         = NULL;
	s.io_inquire.nextrec       = NULL;
	s.io_inquire.number        = NULL;
	s.io_inquire.opened        = NULL;
	s.io_inquire.pad           = NULL;
	s.io_inquire.position      = NULL;
	s.io_inquire.read          = NULL;
	s.io_inquire.readwrite     = NULL;
	s.io_inquire.recl          = NULL;
	s.io_inquire.sequential    = NULL;
	s.io_inquire.unformatted   = NULL;
	s.io_inquire.write         = NULL;

	ofc_parse_call_arg_t* ca_unit        = NULL;
	ofc_parse_call_arg_t* ca_access      = NULL;
	ofc_parse_call_arg_t* ca_action      = NULL;
	ofc_parse_call_arg_t* ca_blank       = NULL;
	ofc_parse_call_arg_t* ca_delim       = NULL;
	ofc_parse_call_arg_t* ca_direct      = NULL;
	ofc_parse_call_arg_t* ca_err         = NULL;
	ofc_parse_call_arg_t* ca_exist       = NULL;
	ofc_parse_call_arg_t* ca_file        = NULL;
	ofc_parse_call_arg_t* ca_form        = NULL;
	ofc_parse_call_arg_t* ca_formatted   = NULL;
	ofc_parse_call_arg_t* ca_iostat      = NULL;
	ofc_parse_call_arg_t* ca_name        = NULL;
	ofc_parse_call_arg_t* ca_named       = NULL;
	ofc_parse_call_arg_t* ca_nextrec     = NULL;
	ofc_parse_call_arg_t* ca_number      = NULL;
	ofc_parse_call_arg_t* ca_opened      = NULL;
	ofc_parse_call_arg_t* ca_pad         = NULL;
	ofc_parse_call_arg_t* ca_position    = NULL;
	ofc_parse_call_arg_t* ca_read        = NULL;
	ofc_parse_call_arg_t* ca_readwrite   = NULL;
	ofc_parse_call_arg_t* ca_recl        = NULL;
	ofc_parse_call_arg_t* ca_sequential  = NULL;
	ofc_parse_call_arg_t* ca_unformatted = NULL;
	ofc_parse_call_arg_t* ca_write       = NULL;

	unsigned i;
	for (i = 0; i < stmt->io.params->count; i++)
	{
		ofc_parse_call_arg_t* param
			= stmt->io.params->call_arg[i];
		if (!param) continue;

		if (ofc_sparse_ref_empty(param->name))
		{
			if (i >= 1)
			{
				ofc_sparse_ref_error(param->src,
					"Un-named parameter %u has no meaning in INQUIRE.", i);
				return NULL;
			}

			if (i == 0)
			{
				ca_unit = param;
			}
		}
		else if (ofc_str_ref_equal_strz_ci(param->name.string, "UNIT"))
		{
			if (ca_unit)
			{
				ofc_sparse_ref_error(param->src,
					"Re-definition of UNIT in INQUIRE.");
				return NULL;
			}

			ca_unit = param;
		}
		else if (ofc_str_ref_equal_strz_ci(param->name.string, "ACCESS"))
		{
			if (ca_access)
			{
				ofc_sparse_ref_error(param->src,
					"Re-definition of ACCESS in INQUIRE.");
				return NULL;
			}

			ca_access = param;
		}
		else if (ofc_str_ref_equal_strz_ci(param->name.string, "ACTION"))
		{
			if (ca_action)
			{
				ofc_sparse_ref_error(param->src,
					"Re-definition of ACTION in INQUIRE.");
				return NULL;
			}

			ca_action = param;
		}
		else if (ofc_str_ref_equal_strz_ci(param->name.string, "BLANK"))
		{
			if (ca_blank)
			{
				ofc_sparse_ref_error(param->src,
					"Re-definition of BLANK in INQUIRE.");
				return NULL;
			}

			ca_blank = param;
		}
		else if (ofc_str_ref_equal_strz_ci(param->name.string, "DELIM"))
		{
			if (ca_delim)
			{
				ofc_sparse_ref_error(param->src,
					"Re-definition of DELIM in INQUIRE.");
				return NULL;
			}

			ca_delim = param;
		}
		else if (ofc_str_ref_equal_strz_ci(param->name.string, "DIRECT"))
		{
			if (ca_direct)
			{
				ofc_sparse_ref_error(param->src,
					"Re-definition of DIRECT in INQUIRE.");
				return NULL;
			}

			ca_direct = param;
		}
		else if (ofc_str_ref_equal_strz_ci(param->name.string, "ERR"))
		{
			if (ca_err)
			{
				ofc_sparse_ref_error(param->src,
					"Re-definition of ERR in INQUIRE.");
				return NULL;
			}

			ca_err = param;
		}
		else if (ofc_str_ref_equal_strz_ci(param->name.string, "EXIST"))
		{
			if (ca_exist)
			{
				ofc_sparse_ref_error(param->src,
					"Re-definition of EXIST in INQUIRE.");
				return NULL;
			}

			ca_exist = param;
		}
		else if (ofc_str_ref_equal_strz_ci(param->name.string, "FILE"))
		{
			if (ca_file)
			{
				ofc_sparse_ref_error(param->src,
					"Re-definition of FILE in INQUIRE.");
				return NULL;
			}

			ca_file = param;
		}
		else if (ofc_str_ref_equal_strz_ci(param->name.string, "FORM"))
		{
			if (ca_form)
			{
				ofc_sparse_ref_error(param->src,
					"Re-definition of FORM in INQUIRE.");
				return NULL;
			}

			ca_form = param;
		}
		else if (ofc_str_ref_equal_strz_ci(param->name.string, "FORMATTED"))
		{
			if (ca_formatted)
			{
				ofc_sparse_ref_error(param->src,
					"Re-definition of FORMATTED in INQUIRE.");
				return NULL;
			}

			ca_formatted = param;
		}
		else if (ofc_str_ref_equal_strz_ci(param->name.string, "IOSTAT"))
		{
			if (ca_iostat)
			{
				ofc_sparse_ref_error(param->src,
					"Re-definition of IOSTAT in INQUIRE.");
				return NULL;
			}

			ca_iostat = param;
		}
		else if (ofc_str_ref_equal_strz_ci(param->name.string, "NAME"))
		{
			if (ca_name)
			{
				ofc_sparse_ref_error(param->src,
					"Re-definition of NAME in INQUIRE.");
				return NULL;
			}

			ca_name = param;
		}
		else if (ofc_str_ref_equal_strz_ci(param->name.string, "NAMED"))
		{
			if (ca_named)
			{
				ofc_sparse_ref_error(param->src,
					"Re-definition of NAMED in INQUIRE.");
				return NULL;
			}

			ca_named = param;
		}
		else if (ofc_str_ref_equal_strz_ci(param->name.string, "NEXTREC"))
		{
			if (ca_nextrec)
			{
				ofc_sparse_ref_error(param->src,
					"Re-definition of NEXTREC in INQUIRE.");
				return NULL;
			}

			ca_nextrec = param;
		}
		else if (ofc_str_ref_equal_strz_ci(param->name.string, "NUMBER"))
		{
			if (ca_number)
			{
				ofc_sparse_ref_error(param->src,
					"Re-definition of NUMBER in INQUIRE.");
				return NULL;
			}

			ca_number = param;
		}
		else if (ofc_str_ref_equal_strz_ci(param->name.string, "OPENED"))
		{
			if (ca_opened)
			{
				ofc_sparse_ref_error(param->src,
					"Re-definition of OPENED in INQUIRE.");
				return NULL;
			}

			ca_opened = param;
		}
		else if (ofc_str_ref_equal_strz_ci(param->name.string, "PAD"))
		{
			if (ca_pad)
			{
				ofc_sparse_ref_error(param->src,
					"Re-definition of PAD in INQUIRE.");
				return NULL;
			}

			ca_pad = param;
		}
		else if (ofc_str_ref_equal_strz_ci(param->name.string, "POSITION"))
		{
			if (ca_position)
			{
				ofc_sparse_ref_error(param->src,
					"Re-definition of POSITION in INQUIRE.");
				return NULL;
			}

			ca_position = param;
		}
		else if (ofc_str_ref_equal_strz_ci(param->name.string, "READ"))
		{
			if (ca_read)
			{
				ofc_sparse_ref_error(param->src,
					"Re-definition of READ in INQUIRE.");
				return NULL;
			}

			ca_read = param;
		}
		else if (ofc_str_ref_equal_strz_ci(param->name.string, "READWRITE"))
		{
			if (ca_readwrite)
			{
				ofc_sparse_ref_error(param->src,
					"Re-definition of READWRITE in INQUIRE.");
				return NULL;
			}

			ca_readwrite = param;
		}
		else if (ofc_str_ref_equal_strz_ci(param->name.string, "RECL"))
		{
			if (ca_recl)
			{
				ofc_sparse_ref_error(param->src,
					"Re-definition of RECL in INQUIRE.");
				return NULL;
			}

			ca_recl = param;
		}
		else if (ofc_str_ref_equal_strz_ci(param->name.string, "SEQUENTIAL"))
		{
			if (ca_sequential)
			{
				ofc_sparse_ref_error(param->src,
					"Re-definition of SEQUENTIAL in INQUIRE.");
				return NULL;
			}

			ca_sequential = param;
		}
		else if (ofc_str_ref_equal_strz_ci(param->name.string, "UNFORMATTED"))
		{
			if (ca_unformatted)
			{
				ofc_sparse_ref_error(param->src,
					"Re-definition of UNFORMATTED in INQUIRE.");
				return NULL;
			}

			ca_unformatted = param;
		}
		else if (ofc_str_ref_equal_strz_ci(param->name.string, "WRITE"))
		{
			if (ca_write)
			{
				ofc_sparse_ref_error(param->src,
					"Re-definition of WRITE in INQUIRE.");
				return NULL;
			}

			ca_write = param;
		}
		else
		{
			ofc_sparse_ref_error(param->src,
				"Unrecognized paramater %u name '%.*s' in INQUIRE.",
				i, param->name.string.size, param->name.string.base);
			return NULL;
		}
	}

	if (!ca_unit && !ca_file)
	{
		ofc_sparse_ref_error(stmt->src,
			"No UNIT or FILE defined in INQUIRE.");
		return NULL;
	}
	else if (ca_unit && ca_file)
	{
		ofc_sparse_ref_error(stmt->src,
			"UNIT and FILE can't be specified at the same time in INQUIRE.");
		return NULL;
	}

	if (ca_unit && (ca_unit->type == OFC_PARSE_CALL_ARG_EXPR))
	{
		s.io_inquire.unit = ofc_sema_expr(
			scope, ca_unit->expr);
		if (!s.io_inquire.unit) return NULL;

		const ofc_sema_type_t* etype
			= ofc_sema_expr_type(s.io_inquire.unit);
		if (!etype)
		{
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}

		if (!ofc_sema_type_is_integer(etype))
		{
			ofc_sparse_ref_error(stmt->src,
				"UNIT must be of type INTEGER in INQUIRE");
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}

		if (!ofc_sema_expr_validate_uint(s.io_inquire.unit))
		{
			ofc_sparse_ref_error(stmt->src,
			   "UNIT must be a positive INTEGER in INQUIRE");
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}
	}
	else if (ca_unit)
	{
		ofc_sparse_ref_error(stmt->src,
			"UNIT must be an INTEGER expression in INQUIRE");
		return NULL;
	}

	if (ca_access)
	{
		s.io_inquire.access = ofc_sema_lhs_from_expr(
			scope, ca_access->expr);
		if (!s.io_inquire.access)
		{
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}

		const ofc_sema_type_t* etype
			= ofc_sema_lhs_type(s.io_inquire.access);
		if (!etype)
		{
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}

		if (!ofc_sema_type_is_character(etype))
		{
			ofc_sparse_ref_error(stmt->src,
				"ACCESS must be a CHARACTER variable in INQUIRE");
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}
	}

	if (ca_action)
	{
		s.io_inquire.action = ofc_sema_lhs_from_expr(
			scope, ca_action->expr);
		if (!s.io_inquire.action)
		{
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}

		const ofc_sema_type_t* etype
			= ofc_sema_lhs_type(s.io_inquire.action);
		if (!etype)
		{
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}

		if (!ofc_sema_type_is_character(etype))
		{
			ofc_sparse_ref_error(stmt->src,
				"ACTION must be a CHARACTER variable in INQUIRE");
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}
	}

	if (ca_blank)
	{
		s.io_inquire.blank = ofc_sema_lhs_from_expr(
			scope, ca_blank->expr);
		if (!s.io_inquire.blank)
		{
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}

		const ofc_sema_type_t* etype
			= ofc_sema_lhs_type(s.io_inquire.blank);
		if (!etype)
		{
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}

		if (!ofc_sema_type_is_character(etype))
		{
			ofc_sparse_ref_error(stmt->src,
				"BLANK must be a CHARACTER variable in INQUIRE");
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}
	}

	if (ca_delim)
	{
		s.io_inquire.delim = ofc_sema_lhs_from_expr(
			scope, ca_delim->expr);
		if (!s.io_inquire.delim)
		{
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}

		const ofc_sema_type_t* etype
			= ofc_sema_lhs_type(s.io_inquire.delim);
		if (!etype)
		{
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}

		if (!ofc_sema_type_is_character(etype))
		{
			ofc_sparse_ref_error(stmt->src,
				"DELIM must be a CHARACTER variable in INQUIRE");
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}
	}

	if (ca_direct)
	{
		s.io_inquire.direct = ofc_sema_lhs_from_expr(
			scope, ca_direct->expr);
		if (!s.io_inquire.direct)
		{
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}

		const ofc_sema_type_t* etype
			= ofc_sema_lhs_type(s.io_inquire.direct);
		if (!etype)
		{
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}

		if (!ofc_sema_type_is_character(etype))
		{
			ofc_sparse_ref_error(stmt->src,
				"DIRECT must be a CHARACTER variable in INQUIRE");
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}
	}

	if (ca_err)
	{
		s.io_inquire.err = ofc_sema_expr(
			scope, ca_err->expr);
		if (!s.io_inquire.err)
		{
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}

		if (!ofc_sema_io_check_label(
			scope, stmt, false,
			s.io_inquire.err, NULL))
		{
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}
	}

	if (ca_exist)
	{
		s.io_inquire.exist = ofc_sema_lhs_from_expr(
			scope, ca_exist->expr);
		if (!s.io_inquire.exist)
		{
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}

		const ofc_sema_type_t* etype
			= ofc_sema_lhs_type(s.io_inquire.exist);
		if (!etype)
		{
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}
		if (!ofc_sema_type_is_logical(etype))
		{
			ofc_sparse_ref_error(stmt->src,
				"EXIST must be a LOGICAL variable in INQUIRE");
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}
	}

	if (ca_file)
	{
		s.io_inquire.file = ofc_sema_expr(
			scope, ca_file->expr);
		if (!s.io_inquire.file)
		{
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}

		const ofc_sema_type_t* etype
			= ofc_sema_expr_type(s.io_inquire.file);
		if (!etype)
		{
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}

		if (!ofc_sema_type_is_character(etype))
		{
			ofc_sparse_ref_error(stmt->src,
				"FILE must be a CHARACTER expression in INQUIRE");
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}
	}

	if (ca_form)
	{
		s.io_inquire.form = ofc_sema_lhs_from_expr(
			scope, ca_form->expr);
		if (!s.io_inquire.form)
		{
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}

		const ofc_sema_type_t* etype
			= ofc_sema_lhs_type(s.io_inquire.form);
		if (!etype)
		{
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}

		if (!ofc_sema_type_is_character(etype))
		{
			ofc_sparse_ref_error(stmt->src,
				"FORM must be a CHARACTER variable in INQUIRE");
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}
	}

	if (ca_formatted)
	{
		s.io_inquire.formatted = ofc_sema_lhs_from_expr(
			scope, ca_formatted->expr);
		if (!s.io_inquire.formatted)
		{
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}

		const ofc_sema_type_t* etype
			= ofc_sema_lhs_type(s.io_inquire.formatted);
		if (!etype)
		{
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}

		if (!ofc_sema_type_is_character(etype))
		{
			ofc_sparse_ref_error(stmt->src,
				"FORMATTED must be a CHARACTER variable in INQUIRE");
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}
	}

	if (ca_iostat)
	{
		s.io_inquire.iostat = ofc_sema_lhs_from_expr(
			scope, ca_iostat->expr);
		if (!s.io_inquire.iostat)
		{
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}

		const ofc_sema_type_t* etype
			= ofc_sema_lhs_type(s.io_inquire.iostat);
		if (!etype)
		{
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}

		if (!ofc_sema_type_is_integer(etype))
		{
			ofc_sparse_ref_error(stmt->src,
				"IOSTAT must be of type INTEGER in INQUIRE");
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}
	}

	if (ca_name)
	{
		s.io_inquire.name = ofc_sema_lhs_from_expr(
			scope, ca_name->expr);
		if (!s.io_inquire.name)
		{
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}

		const ofc_sema_type_t* etype
			= ofc_sema_lhs_type(s.io_inquire.name);
		if (!etype)
		{
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}

		if (!ofc_sema_type_is_character(etype))
		{
			ofc_sparse_ref_error(stmt->src,
				"NAME must be a CHARACTER variable in INQUIRE");
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}
	}

	if (ca_named)
	{
		s.io_inquire.named = ofc_sema_lhs_from_expr(
			scope, ca_named->expr);
		if (!s.io_inquire.named)
		{
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}

		const ofc_sema_type_t* etype
			= ofc_sema_lhs_type(s.io_inquire.named);
		if (!etype)
		{
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}

		if (!ofc_sema_type_is_logical(etype))
		{
			ofc_sparse_ref_error(stmt->src,
				"NAMED must be a LOGICAL variable in INQUIRE");
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}
	}

	if (ca_nextrec)
	{
		s.io_inquire.nextrec = ofc_sema_lhs_from_expr(
			scope, ca_nextrec->expr);
		if (!s.io_inquire.nextrec)
		{
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}

		const ofc_sema_type_t* etype
			= ofc_sema_lhs_type(s.io_inquire.nextrec);
		if (!etype)
		{
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}

		if (!ofc_sema_type_is_integer(etype))
		{
			ofc_sparse_ref_error(stmt->src,
				"NEXTREC must be of type INTEGER in INQUIRE");
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}
	}

	if (ca_number)
	{
		s.io_inquire.number = ofc_sema_lhs_from_expr(
			scope, ca_number->expr);
		if (!s.io_inquire.number)
		{
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}

		const ofc_sema_type_t* etype
			= ofc_sema_lhs_type(s.io_inquire.number);
		if (!etype)
		{
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}

		if (!ofc_sema_type_is_integer(etype))
		{
			ofc_sparse_ref_error(stmt->src,
				"NUMBER must be an INTEGER variable in INQUIRE");
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}
	}

	if (ca_opened)
	{
		s.io_inquire.opened = ofc_sema_lhs_from_expr(
			scope, ca_opened->expr);
		if (!s.io_inquire.opened)
		{
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}

		const ofc_sema_type_t* etype
			= ofc_sema_lhs_type(s.io_inquire.opened);
		if (!etype)
		{
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}

		if (!ofc_sema_type_is_logical(etype))
		{
			ofc_sparse_ref_error(stmt->src,
				"OPENED must be a LOGICAL variable in INQUIRE");
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}
	}

	if (ca_pad)
	{
		s.io_inquire.pad = ofc_sema_lhs_from_expr(
			scope, ca_pad->expr);
		if (!s.io_inquire.pad)
		{
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}

		const ofc_sema_type_t* etype
			= ofc_sema_lhs_type(s.io_inquire.pad);
		if (!etype)
		{
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}

		if (!ofc_sema_type_is_character(etype))
		{
			ofc_sparse_ref_error(stmt->src,
				"PAD must be a CHARACTER variable in INQUIRE");
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}
	}

	if (ca_position)
	{
		s.io_inquire.position = ofc_sema_lhs_from_expr(
			scope, ca_position->expr);
		if (!s.io_inquire.position)
		{
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}

		const ofc_sema_type_t* etype
			= ofc_sema_lhs_type(s.io_inquire.position);
		if (!etype)
		{
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}

		if (!ofc_sema_type_is_character(etype))
		{
			ofc_sparse_ref_error(stmt->src,
				"POSITION must be a CHARACTER variable in INQUIRE");
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}
	}

	if (ca_read)
	{
		s.io_inquire.read = ofc_sema_lhs_from_expr(
			scope, ca_read->expr);
		if (!s.io_inquire.read)
		{
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}

		const ofc_sema_type_t* etype
			= ofc_sema_lhs_type(s.io_inquire.read);
		if (!etype)
		{
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}

		if (!ofc_sema_type_is_character(etype))
		{
			ofc_sparse_ref_error(stmt->src,
				"READ must be a CHARACTER variable in INQUIRE");
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}
	}

	if (ca_readwrite)
	{
		s.io_inquire.readwrite = ofc_sema_lhs_from_expr(
			scope, ca_readwrite->expr);
		if (!s.io_inquire.readwrite)
		{
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}

		const ofc_sema_type_t* etype
			= ofc_sema_lhs_type(s.io_inquire.readwrite);
		if (!etype)
		{
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}

		if (!ofc_sema_type_is_character(etype))
		{
			ofc_sparse_ref_error(stmt->src,
				"READWRITE must be a CHARACTER variable in INQUIRE");
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}
	}

	if (ca_recl)
	{
		s.io_inquire.recl = ofc_sema_lhs_from_expr(
			scope, ca_recl->expr);
		if (!s.io_inquire.recl)
		{
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}

		const ofc_sema_type_t* etype
			= ofc_sema_lhs_type(s.io_inquire.recl);
		if (!etype)
		{
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}

		if (!ofc_sema_type_is_integer(etype))
		{
			ofc_sparse_ref_error(stmt->src,
				"RECL must be an INTEGER variable in INQUIRE");
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}
	}

	if (ca_sequential)
	{
		s.io_inquire.sequential = ofc_sema_lhs_from_expr(
			scope, ca_sequential->expr);
		if (!s.io_inquire.sequential)
		{
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}

		const ofc_sema_type_t* etype
			= ofc_sema_lhs_type(s.io_inquire.sequential);
		if (!etype)
		{
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}

		if (!ofc_sema_type_is_character(etype))
		{
			ofc_sparse_ref_error(stmt->src,
				"SEQUENTIAL must be a CHARACTER variable in INQUIRE");
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}
	}

	if (ca_unformatted)
	{
		s.io_inquire.unformatted = ofc_sema_lhs_from_expr(
			scope, ca_unformatted->expr);
		if (!s.io_inquire.unformatted)
		{
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}

		const ofc_sema_type_t* etype
			= ofc_sema_lhs_type(s.io_inquire.unformatted);
		if (!etype)
		{
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}

		if (!ofc_sema_type_is_character(etype))
		{
			ofc_sparse_ref_error(stmt->src,
				"UNFORMATTED must be a CHARACTER variable in INQUIRE");
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}
	}

	if (ca_write)
	{
		s.io_inquire.write = ofc_sema_lhs_from_expr(
			scope, ca_write->expr);
		if (!s.io_inquire.write)
		{
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}

		const ofc_sema_type_t* etype
			= ofc_sema_lhs_type(s.io_inquire.write);
		if (!etype)
		{
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}

		if (!ofc_sema_type_is_character(etype))
		{
			ofc_sparse_ref_error(stmt->src,
				"WRITE must be a CHARACTER variable in INQUIRE");
			ofc_sema_stmt_io_inquire__cleanup(s);
			return NULL;
		}
	}

	ofc_sema_stmt_t* as
		= ofc_sema_stmt_alloc(s);
	if (!as)
	{
		ofc_sema_stmt_io_inquire__cleanup(s);
		return NULL;
	}
	return as;
}
Exemple #5
0
Fichier : do.c Projet : franred/ofc
static ofc_sema_stmt_t* ofc_sema_stmt_do_while__block(
	ofc_sema_scope_t* scope,
	const ofc_parse_stmt_t* stmt)
{

	if (!stmt
		|| (stmt->type != OFC_PARSE_STMT_DO_WHILE_BLOCK)
		|| !stmt->do_while_block.cond)
		return NULL;

	ofc_sema_stmt_t s;
	s.type = OFC_SEMA_STMT_DO_WHILE_BLOCK;

	s.do_while_block.cond = ofc_sema_expr(
		scope, stmt->do_while_block.cond);
	if (!s.do_while_block.cond)
		return NULL;

	const ofc_sema_type_t* type
		= ofc_sema_expr_type(s.do_while_block.cond);
	if (!ofc_sema_type_is_logical(type))
	{
		ofc_sparse_ref_error(stmt->do_while_block.cond->src,
			"IF condition type must be LOGICAL.");

		ofc_sema_expr_delete(s.do_while_block.cond);
		return NULL;
	}

	s.do_while_block.block = NULL;
	if (stmt->do_while_block.block)
	{
		s.do_while_block.block
			= ofc_sema_stmt_list(
				scope, stmt->do_while_block.block);

		if (!s.do_while_block.block)
		{
			ofc_sema_expr_delete(s.do_while_block.cond);
			return NULL;
		}
	}

	ofc_sema_stmt_t* as = ofc_sema_stmt_alloc(s);
	if (!as)
	{
		ofc_sema_stmt_list_delete(s.do_while_block.block);
		ofc_sema_expr_delete(s.do_while_block.cond);
		return NULL;
	}

	if (stmt->do_while_block.end_do_has_label
		&& !ofc_sema_label_map_add_end_block(
			scope->label, stmt->do_while_block.end_do_label, as))
	{
		ofc_sema_stmt_delete(as);
		return NULL;
	}

	return as;
}
Exemple #6
0
Fichier : do.c Projet : franred/ofc
static bool ofc_sema_stmt__loop_control(
	ofc_sema_scope_t* scope,
	const ofc_parse_assign_t* parse_init,
	const ofc_parse_expr_t*   parse_last,
	const ofc_parse_expr_t*   parse_step,
	ofc_sema_lhs_t**  sema_iter,
	ofc_sema_expr_t** sema_init,
	ofc_sema_expr_t** sema_last,
	ofc_sema_expr_t** sema_step)
{
	*sema_iter = ofc_sema_lhs(
		scope, parse_init->name);
	if (!*sema_iter) return false;

	const ofc_sema_type_t* dtype
		= ofc_sema_lhs_type(*sema_iter);
	if (!ofc_sema_type_is_scalar(dtype))
	{
		ofc_sparse_ref_error(parse_init->name->src,
			"DO loop iterator must be a scalar type.");
		ofc_sema_lhs_delete(*sema_iter);
		return false;
	}

	if (!ofc_sema_type_is_integer(dtype))
	{
		ofc_sparse_ref_warning(parse_init->name->src,
			"Using REAL in DO loop iterator.");
	}

	*sema_init = ofc_sema_expr(
		scope, parse_init->init);
	if (!*sema_init)
	{
		ofc_sema_lhs_delete(*sema_iter);
		return false;
	}

	if (!ofc_sema_type_compatible(dtype,
		ofc_sema_expr_type(*sema_init)))
	{
		ofc_sema_expr_t* cast
			= ofc_sema_expr_cast(*sema_init, dtype);
		if (!cast)
		{
			const ofc_sema_type_t* expr_type
				= ofc_sema_expr_type(*sema_init);
			ofc_sparse_ref_error(parse_init->init->src,
				"Expression type %s doesn't match lhs type %s",
				ofc_sema_type_str_rep(expr_type),
				ofc_sema_type_str_rep(dtype));
			ofc_sema_expr_delete(*sema_init);
			ofc_sema_lhs_delete(*sema_iter);
			return false;
		}
		*sema_init = cast;
	}

	*sema_last = ofc_sema_expr(
		scope, parse_last);
	if (!*sema_last)
	{
		ofc_sema_expr_delete(*sema_init);
		ofc_sema_lhs_delete(*sema_iter);
		return false;
	}

	if (!ofc_sema_type_compatible(dtype,
		ofc_sema_expr_type(*sema_last)))
	{
		ofc_sema_expr_t* cast
			= ofc_sema_expr_cast(*sema_last, dtype);
		if (!cast)
		{
			const ofc_sema_type_t* expr_type =
				ofc_sema_expr_type(*sema_last);
			ofc_sparse_ref_error(parse_last->src,
				"Expression type %s doesn't match lhs type %s",
				ofc_sema_type_str_rep(expr_type),
				ofc_sema_type_str_rep(dtype));
			ofc_sema_expr_delete(*sema_init);
			ofc_sema_expr_delete(*sema_last);
			ofc_sema_lhs_delete(*sema_iter);
			return false;
		}
		*sema_last = cast;
	}

	*sema_step = NULL;
	if (parse_step)
	{
		*sema_step = ofc_sema_expr(
			scope, parse_step);
		if (!*sema_step)
		{
			ofc_sema_expr_delete(*sema_init);
			ofc_sema_expr_delete(*sema_last);
			ofc_sema_lhs_delete(*sema_iter);
			return false;
		}

		if (!ofc_sema_type_compatible(dtype,
			ofc_sema_expr_type(*sema_step)))
		{
			ofc_sema_expr_t* cast
				= ofc_sema_expr_cast(*sema_step, dtype);
			if (!cast)
			{
				const ofc_sema_type_t* expr_type =
					ofc_sema_expr_type(*sema_step);
				ofc_sparse_ref_error(parse_step->src,
					"Expression type %s doesn't match lhs type %s",
					ofc_sema_type_str_rep(expr_type),
					ofc_sema_type_str_rep(dtype));
				ofc_sema_expr_delete(*sema_step);
				ofc_sema_expr_delete(*sema_init);
				ofc_sema_expr_delete(*sema_last);
				ofc_sema_lhs_delete(*sema_iter);
				return false;
			}
			*sema_step = cast;
		}
	}

	return true;
}
Exemple #7
0
static ofc_sema_lhs_t* ofc_sema_lhs_substring(
	ofc_sema_scope_t* scope,
	ofc_sema_lhs_t* lhs,
	const ofc_parse_array_index_t* index)
{
	if (!ofc_sema_lhs_reference(lhs))
		return NULL;

	if (!index
		|| (index->count != 1)
		|| !lhs->data_type)
	{
		ofc_sema_lhs_delete(lhs);
		return NULL;
	}

	const ofc_parse_array_range_t* range
		= index->range[0];
	if (!range || range->stride)
	{
		ofc_sema_lhs_delete(lhs);
		return NULL;
	}

	ofc_sema_expr_t* first
		= ofc_sema_expr(scope, range->first);
	if (range->first && !first)
	{
		ofc_sema_lhs_delete(lhs);
		return NULL;
	}

	ofc_sema_expr_t* last = NULL;
	if (range->last)
	{
		last = ofc_sema_expr(scope, range->last);
		if (!last)
		{
			ofc_sema_lhs_delete(lhs);
			ofc_sema_expr_delete(first);
			return NULL;
		}
	}
	else if (!range->is_slice)
	{
		last = first;
	}

	unsigned len = 0;
	bool len_var = true;
	if ((!first || ofc_sema_expr_is_constant(first))
		&& ofc_sema_expr_is_constant(last))
	{
		const ofc_sema_typeval_t* first_ctv
			= ofc_sema_expr_constant(first);
		const ofc_sema_typeval_t* last_ctv
			= ofc_sema_expr_constant(last);

		if ((first && !first_ctv) || !last_ctv)
		{
			ofc_sema_lhs_delete(lhs);
			if (last != first)
				ofc_sema_expr_delete(last);
			ofc_sema_expr_delete(first);
			return NULL;
		}

		int64_t ifirst = 1;
		if (first && !ofc_sema_typeval_get_integer(
			first_ctv, &ifirst))
		{
			ofc_sema_lhs_delete(lhs);
			if (last != first)
				ofc_sema_expr_delete(last);
			ofc_sema_expr_delete(first);
			return NULL;
		}

		int64_t ilast;
		if (!ofc_sema_typeval_get_integer(
			last_ctv, &ilast))
		{
			ofc_sema_lhs_delete(lhs);
			if (last != first)
				ofc_sema_expr_delete(last);
			ofc_sema_expr_delete(first);
			return NULL;
		}

		if (ifirst < 0)
		{
			ofc_sparse_ref_error(lhs->src,
				"First index in character substring must be 1 or greater");

			ofc_sema_lhs_delete(lhs);
			if (last != first)
				ofc_sema_expr_delete(last);
			ofc_sema_expr_delete(first);
			return NULL;
		}

		if (ilast < ifirst)
		{
			ofc_sparse_ref_error(lhs->src,
				"Last index in character substring must be greater than first");

			ofc_sema_lhs_delete(lhs);
			if (last != first)
				ofc_sema_expr_delete(last);
			ofc_sema_expr_delete(first);
			return NULL;
		}

		if ((lhs->data_type->len > 0)
			&& (ilast > lhs->data_type->len))
		{
			ofc_sparse_ref_warning(lhs->src,
				"Last index in character substring out-of-bounds");
		}

		int64_t ilen = (ilast - ifirst) + 1;
		len = ilen;
		if ((int64_t)len != ilen)
		{
			ofc_sema_lhs_delete(lhs);
			if (last != first)
				ofc_sema_expr_delete(last);
			ofc_sema_expr_delete(first);
			return NULL;
		}
		len_var = false;
	}

	const ofc_sema_type_t* type
		= ofc_sema_type_create_character(
			lhs->data_type->kind, len, len_var);
	if (!type)
	{
		ofc_sema_lhs_delete(lhs);
		if (last != first)
			ofc_sema_expr_delete(last);
		ofc_sema_expr_delete(first);
		return NULL;
	}

	ofc_sema_lhs_t* alhs
		= (ofc_sema_lhs_t*)malloc(
			sizeof(ofc_sema_lhs_t));
	if (!alhs)
	{
		if (last != first)
			ofc_sema_expr_delete(last);
		ofc_sema_expr_delete(first);
		ofc_sema_lhs_delete(lhs);
		return NULL;
	}

	alhs->type            = OFC_SEMA_LHS_SUBSTRING;
	alhs->src             = lhs->src;
	alhs->parent          = lhs;
	alhs->substring.first = first;
	alhs->substring.last  = last;
	alhs->data_type       = type;
	alhs->refcnt          = 0;

	return alhs;
}
Exemple #8
0
static ofc_sema_lhs_t* ofc_sema_lhs__implicit_do(
	ofc_sema_scope_t* scope,
	ofc_sparse_ref_t src,
	const ofc_parse_lhs_implicit_do_t* id)
{
	if (!id || !id->init)
		return NULL;

	ofc_sema_lhs_t* lhs
		= (ofc_sema_lhs_t*)malloc(
			sizeof(ofc_sema_lhs_t));
	if (!lhs) return NULL;

	lhs->type = OFC_SEMA_LHS_IMPLICIT_DO;
	lhs->src  = src;

	lhs->implicit_do.lhs  = NULL;
	lhs->implicit_do.iter = NULL;
	lhs->implicit_do.init = NULL;
	lhs->implicit_do.last = NULL;
	lhs->implicit_do.step = NULL;

	lhs->implicit_do.count_var = true;
	lhs->implicit_do.count = 0;

	lhs->data_type = NULL;
	lhs->refcnt = 0;

	ofc_sema_lhs_t* iter_lhs = ofc_sema_lhs_from_expr(
		scope, id->iter);
	if (!iter_lhs)
	{
		ofc_sema_lhs_delete(lhs);
		return NULL;
	}
	if (!ofc_sema_lhs_mark_used(
		iter_lhs, true, true))
	{
		ofc_sema_lhs_delete(iter_lhs);
		ofc_sema_lhs_delete(lhs);
		return NULL;
	}

	if (iter_lhs->type != OFC_SEMA_LHS_DECL)
	{
		ofc_sparse_ref_error(id->iter->src,
			"Implicit do loop iterator must be a variable");
		ofc_sema_lhs_delete(iter_lhs);
		ofc_sema_lhs_delete(lhs);
		return NULL;
	}

	if (!ofc_sema_decl_reference(iter_lhs->decl))
	{
		ofc_sema_lhs_delete(iter_lhs);
		ofc_sema_lhs_delete(lhs);
		return NULL;
	}

	lhs->implicit_do.iter = iter_lhs->decl;
	ofc_sema_lhs_delete(iter_lhs);

	const ofc_sema_type_t* iter_type
		= ofc_sema_decl_type(lhs->implicit_do.iter);
	if (!iter_type)
	{
		ofc_sema_lhs_delete(lhs);
		return NULL;
	}

	if (!ofc_sema_type_is_scalar(iter_type))
	{
		ofc_sparse_ref_error(id->iter->src,
			"Implicit do loop iterator must be a scalar type");
		ofc_sema_lhs_delete(lhs);
		return NULL;
	}

	if (!ofc_sema_type_is_integer(iter_type))
	{
		ofc_sparse_ref_warning(id->iter->src,
			"Using REAL in implicit do loop iterator");
	}

	lhs->implicit_do.init = ofc_sema_expr(
		scope, id->init);
	if (!lhs->implicit_do.init)
	{
		ofc_sema_lhs_delete(lhs);
		return NULL;
	}

	const ofc_sema_type_t* init_type
		= ofc_sema_expr_type(lhs->implicit_do.init);
	if (!init_type)
	{
		ofc_sema_lhs_delete(lhs);
		return NULL;
	}
	else if (!ofc_sema_type_compatible(
		iter_type, init_type))
	{
		ofc_sema_expr_t* cast
			= ofc_sema_expr_cast(
				lhs->implicit_do.init, iter_type);
		if (!cast)
		{
			ofc_sema_lhs_delete(lhs);
			return NULL;
		}

		lhs->implicit_do.init = cast;
	}

	lhs->implicit_do.last = ofc_sema_expr(
		scope, id->limit);
	if (!lhs->implicit_do.last)
	{
		ofc_sema_lhs_delete(lhs);
		return NULL;
	}

	const ofc_sema_type_t* last_type
		= ofc_sema_expr_type(lhs->implicit_do.last);
	if (!last_type)
	{
		ofc_sema_lhs_delete(lhs);
		return NULL;
	}
	else if (!ofc_sema_type_compatible(
		iter_type, last_type))
	{
		ofc_sema_expr_t* cast
			= ofc_sema_expr_cast(
				lhs->implicit_do.last, iter_type);
		if (!cast)
		{
			ofc_sparse_ref_error(id->limit->src,
				"Expression type '%s' doesn't match iterator type '%s'",
				ofc_sema_type_str_rep(last_type),
				ofc_sema_type_str_rep(iter_type));
			ofc_sema_lhs_delete(lhs);
			return NULL;
		}

		lhs->implicit_do.last = cast;
	}

	if (id->step)
	{
		lhs->implicit_do.step
			= ofc_sema_expr(scope, id->step);
		if (!lhs->implicit_do.step)
		{
			ofc_sema_lhs_delete(lhs);
			return NULL;
		}

		const ofc_sema_type_t* step_type
			= ofc_sema_expr_type(lhs->implicit_do.step);
		if (!step_type)
		{
			ofc_sema_lhs_delete(lhs);
			return NULL;
		}
		else if (!ofc_sema_type_compatible(
			iter_type, step_type))
		{
			ofc_sema_expr_t* cast
				= ofc_sema_expr_cast(
					lhs->implicit_do.step, iter_type);
			if (!cast)
			{
				ofc_sparse_ref_error(id->step->src,
					"Expression type '%s' doesn't match iterator type '%s'",
					ofc_sema_type_str_rep(step_type),
					ofc_sema_type_str_rep(iter_type));
				ofc_sema_lhs_delete(lhs);
				return NULL;
			}

			lhs->implicit_do.step = cast;
		}
	}

	if (id->dlist && (id->dlist->count > 0))
	{
		lhs->implicit_do.lhs
			= ofc_sema_lhs_list_id(scope, id->dlist);
		if (!lhs->implicit_do.lhs)
		{
			ofc_sema_lhs_delete(lhs);
			return NULL;
		}
	}
	else
	{
		ofc_sema_lhs_delete(lhs);
		return NULL;
	}

	const ofc_sema_typeval_t* ctv[3];
	ctv[0] = ofc_sema_expr_constant(
			lhs->implicit_do.init);
	ctv[1] = ofc_sema_expr_constant(
			lhs->implicit_do.last);
	ctv[2] = ofc_sema_expr_constant(
			lhs->implicit_do.step);

	long double first, last, step = 1.0;
	if (ofc_sema_typeval_get_real(ctv[0], &first)
		&& ofc_sema_typeval_get_real(ctv[1], &last)
		&& (!ctv[2] || ofc_sema_typeval_get_real(ctv[2], &step)))
	{
		long double dcount = floor((last - first) / step);
		if (dcount < 0.0)
		{
			ofc_sparse_ref_error(src,
				"Loop iterates away from limit");
			ofc_sema_lhs_delete(lhs);
			return NULL;
		}
		dcount += 1.0;

		lhs->implicit_do.count = (unsigned)dcount;
		if ((long double)lhs->implicit_do.count != dcount)
		{
			ofc_sema_lhs_delete(lhs);
			return NULL;
		}
		lhs->implicit_do.count_var = false;
	}
	else
	{
		lhs->implicit_do.count_var = true;
		lhs->implicit_do.count     = 0;
	}

	return lhs;
}
Exemple #9
0
ofc_sema_stmt_t* ofc_sema_stmt_io_position(
	ofc_sema_scope_t* scope,
	const ofc_parse_stmt_t* stmt)
{
	if (!scope || !stmt
		|| !stmt->io.params)
		return NULL;

	const char* name;
	ofc_sema_stmt_t s;

	switch (stmt->type)
	{
		case OFC_PARSE_STMT_IO_REWIND:
			s.type = OFC_SEMA_STMT_IO_REWIND;
			name = "REWIND";
			break;
		case OFC_PARSE_STMT_IO_END_FILE:
			s.type = OFC_SEMA_STMT_IO_END_FILE;
			name = "ENDFILE";
			break;
		case OFC_PARSE_STMT_IO_BACKSPACE:
			s.type = OFC_SEMA_STMT_IO_BACKSPACE;
			name = "BACKSPACE";
			break;
		default:
			return NULL;
	}

	s.io_position.unit        = NULL;
	s.io_position.iostat      = NULL;
	s.io_position.err         = NULL;

	ofc_parse_call_arg_t* ca_unit   = NULL;
	ofc_parse_call_arg_t* ca_iostat = NULL;
	ofc_parse_call_arg_t* ca_err    = NULL;

	unsigned i;
	for (i = 0; i < stmt->io.params->count; i++)
	{
		ofc_parse_call_arg_t* param
			= stmt->io.params->call_arg[i];
		if (!param) continue;

		if (ofc_sparse_ref_empty(param->name))
		{
			if (i >= 1)
			{
				ofc_sparse_ref_error(param->src,
					"Un-named parameter %u has no meaning in %s.", i, name);
				return NULL;
			}

			if (i == 0)
			{
				ca_unit = param;
			}
		}
		else if (ofc_str_ref_equal_strz_ci(param->name.string, "UNIT"))
		{
			if (ca_unit)
			{
				ofc_sparse_ref_error(param->src,
					"Re-definition of UNIT in %s.", name);
				return NULL;
			}

			ca_unit = param;
		}
		else if (ofc_str_ref_equal_strz_ci(param->name.string, "IOSTAT"))
		{
			if (ca_iostat)
			{
				ofc_sparse_ref_error(param->src,
					"Re-definition of IOSTAT in %s.", name);
				return NULL;
			}

			ca_iostat = param;
		}
		else if (ofc_str_ref_equal_strz_ci(param->name.string, "ERR"))
		{
			if (ca_err)
			{
				ofc_sparse_ref_error(param->src,
					"Re-definition of ERR in %s.", name);
				return NULL;
			}

			ca_err = param;
		}
		else
		{
			ofc_sparse_ref_error(param->src,
				"Unrecognized paramater %u name '%.*s' in %s.",
				i, param->name.string.size, param->name.string.base, name);
			return NULL;
		}
	}

	if (!ca_unit)
	{
		ofc_sparse_ref_error(stmt->src,
			"No UNIT defined in %s.", name);
		return NULL;
	}

	if (ca_unit->type == OFC_PARSE_CALL_ARG_EXPR)
	{
		s.io_position.unit = ofc_sema_expr(
			scope, ca_unit->expr);
		if (!s.io_position.unit) return NULL;

		const ofc_sema_type_t* etype
			= ofc_sema_expr_type(s.io_position.unit);
		if (!etype) return NULL;

		if (!ofc_sema_type_is_integer(etype))
		{
			ofc_sparse_ref_error(stmt->src,
				"UNIT must be of type INTEGER in %s", name);
			ofc_sema_expr_delete(s.io_position.unit);
			return NULL;
		}

		if (!ofc_sema_expr_validate_uint(s.io_position.unit))
		{
			ofc_sparse_ref_error(stmt->src,
				   "UNIT must be a positive INTEGER in %s", name);
			ofc_sema_expr_delete(s.io_position.unit);
			return NULL;
		}
	}
	else
	{
		ofc_sparse_ref_error(stmt->src,
			"UNIT must be an INTEGER expression in %s", name);
		return NULL;
	}

	if (ca_iostat)
	{
		s.io_position.iostat = ofc_sema_expr(
			scope, ca_iostat->expr);
		if (!s.io_position.iostat)
		{
			ofc_sema_expr_delete(s.io_position.unit);
			return NULL;
		}

		if (s.io_position.iostat->type != OFC_SEMA_EXPR_LHS)
		{
			ofc_sparse_ref_error(stmt->src,
				"IOSTAT must be of a variable in %s", name);
			ofc_sema_expr_delete(s.io_position.unit);
			ofc_sema_expr_delete(s.io_position.iostat);
			return NULL;
		}

		const ofc_sema_type_t* etype
			= ofc_sema_expr_type(s.io_position.iostat);
		if (!etype)
		{
			ofc_sema_expr_delete(s.io_position.unit);
			ofc_sema_expr_delete(s.io_position.iostat);
			return NULL;
		}

		if (!ofc_sema_type_is_integer(etype))
		{
			ofc_sparse_ref_error(stmt->src,
				"IOSTAT must be of type INTEGER in %s", name);
			ofc_sema_expr_delete(s.io_position.unit);
			ofc_sema_expr_delete(s.io_position.iostat);
			return NULL;
		}

	}

	if (ca_err)
	{
		s.io_position.err = ofc_sema_expr_label(
			scope, ca_err->expr);
		if (!s.io_position.err)
		{
			ofc_sema_expr_delete(s.io_position.unit);
			ofc_sema_expr_delete(s.io_position.iostat);
			return NULL;
		}
	}

	ofc_sema_stmt_t* as
		= ofc_sema_stmt_alloc(s);
	if (!as)
	{
		ofc_sema_expr_delete(s.io_position.unit);
		ofc_sema_expr_delete(s.io_position.iostat);
		ofc_sema_expr_delete(s.io_position.err);
		return NULL;
	}
	return as;
}