Esempio n. 1
0
TypedResult<TypeSpecifier> BinaryExpression::ComputeResultType(
		const_shared_ptr<Expression> left, const_shared_ptr<Expression> right,
		const OperatorType op,
		const shared_ptr<ExecutionContext> execution_context) {
	auto left_type_specifier_result = left->GetTypeSpecifier(execution_context,
			AliasResolution::RESOLVE);
	auto right_type_specifier_result = right->GetTypeSpecifier(
			execution_context, AliasResolution::RESOLVE);

	auto errors = left_type_specifier_result.GetErrors();
	if (ErrorList::IsTerminator(errors)) {
		errors = right_type_specifier_result.GetErrors();
		if (ErrorList::IsTerminator(errors)) {
			const_shared_ptr<PrimitiveTypeSpecifier> left_as_primitive =
					std::dynamic_pointer_cast<const PrimitiveTypeSpecifier>(
							left_type_specifier_result.GetData());
			const_shared_ptr<PrimitiveTypeSpecifier> right_as_primitive =
					std::dynamic_pointer_cast<const PrimitiveTypeSpecifier>(
							right_type_specifier_result.GetData());

			if (left_as_primitive
					&& left_as_primitive != PrimitiveTypeSpecifier::GetNone()
					&& right_as_primitive
					&& right_as_primitive
							!= PrimitiveTypeSpecifier::GetNone()) {

				const BasicType left_basic_type =
						left_as_primitive->GetBasicType();
				const BasicType right_basic_type =
						right_as_primitive->GetBasicType();

				if (op == EQUAL || op == NOT_EQUAL || op == LESS_THAN
						|| op == LESS_THAN_EQUAL || op == GREATER_THAN
						|| op == GREATER_THAN_EQUAL || op == AND || op == OR) {
					return TypedResult<TypeSpecifier>(
							PrimitiveTypeSpecifier::GetBoolean(), errors);
				}

				if (op == MOD) {
					return TypedResult<TypeSpecifier>(
							PrimitiveTypeSpecifier::GetInt(), errors);
				}

				if (right_basic_type >= left_basic_type) {
					return TypedResult<TypeSpecifier>(right_as_primitive,
							errors);
				} else {
					return TypedResult<TypeSpecifier>(left_as_primitive, errors);
				}
			} else {
				errors = ErrorList::From(
						make_shared<Error>(Error::SEMANTIC,
								Error::INVALID_TYPE_COMBINATION,
								right->GetLocation().begin), errors);
			}
		}
	}

	return TypedResult<TypeSpecifier>(nullptr, errors);
}
const PreprocessResult ComplexInstantiationStatement::Preprocess(
		const shared_ptr<ExecutionContext> context,
		const shared_ptr<ExecutionContext> closure,
		const_shared_ptr<TypeSpecifier> return_type_specifier) const {
	auto type_result = m_type_specifier->GetType(context->GetTypeTable());

	auto errors = type_result->GetErrors();
	if (ErrorList::IsTerminator(errors)) {
		auto type = type_result->GetData<TypeDefinition>();
		auto as_complex = dynamic_pointer_cast<const ComplexType>(type);
		if (as_complex) {
			auto existing = context->GetSymbol(GetName(), SHALLOW);
			if (existing == Symbol::GetDefaultSymbol()) {
				auto result = as_complex->PreprocessSymbol(context,
						m_type_specifier, GetInitializerExpression());

				errors = result->GetErrors();
				if (ErrorList::IsTerminator(errors)) {
					auto symbol = result->GetData<Symbol>();
					if (symbol) {
						auto name = *GetName();
						const InsertResult insert_result =
								context->InsertSymbol(name, symbol);

						if (insert_result != INSERT_SUCCESS) {
							assert(false);
						}
					} else {
						assert(false);
					}
				}
			} else {
				//symbol already exists
				errors = ErrorList::From(
						make_shared<Error>(Error::SEMANTIC,
								Error::PREVIOUS_DECLARATION,
								m_type_specifier_location.begin,
								*GetName()), errors);
			}
		} else {
			errors = ErrorList::From(
					make_shared<Error>(Error::SEMANTIC,
							Error::NOT_A_COMPOUND_TYPE,
							m_type_specifier_location.begin,
							m_type_specifier->ToString()), errors);
		}
	}

	return PreprocessResult(PreprocessResult::ReturnCoverage::NONE, errors);
}
Esempio n. 3
0
const AnalysisResult PrimitiveTypeSpecifier::AnalyzeAssignmentTo(
		const_shared_ptr<TypeSpecifier> other,
		const TypeTable& type_table) const {
	auto resolved_other_result = NestedTypeSpecifier::Resolve(other,
			type_table);

	if (ErrorList::IsTerminator(resolved_other_result.GetErrors())) {
		auto resolved_other = resolved_other_result.GetData();

		auto widening_analysis = resolved_other->AnalyzeWidening(type_table,
				*this);
		if (widening_analysis != AnalysisResult::INCOMPATIBLE) {
			return widening_analysis;
		}

		auto other_as_primitive = dynamic_pointer_cast<
				const PrimitiveTypeSpecifier>(resolved_other);
		if (other_as_primitive) {
			const BasicType other_type = other_as_primitive->GetBasicType();
			if (other_type != BasicType::NONE) {
				if (m_basic_type == other_type) {
					return AnalysisResult::EQUIVALENT;
				} else if (m_basic_type < other_type) {
					return AnalysisResult::UNAMBIGUOUS;
				}
			}
		}
	}

	return INCOMPATIBLE;
}
Esempio n. 4
0
const ExecutionResult InvokeStatement::Execute(
		const shared_ptr<ExecutionContext> context,
		const shared_ptr<ExecutionContext> closure) const {
	auto result = m_expression->Evaluate(context, closure);

	return ExecutionResult(result->GetErrors());
}
Esempio n. 5
0
const PreprocessResult ExitStatement::Preprocess(
		const shared_ptr<ExecutionContext> context,
		const shared_ptr<ExecutionContext> closure,
		const_shared_ptr<TypeSpecifier> return_type_specifier) const {
	ErrorListRef errors = ErrorList::GetTerminator();

	if (m_exit_expression) {
		auto expression_type_specifier_result =
				m_exit_expression->GetTypeSpecifier(context);

		errors = expression_type_specifier_result.GetErrors();
		if (ErrorList::IsTerminator(errors)) {
			auto expression_type_specifier =
					expression_type_specifier_result.GetData();

			const_shared_ptr<PrimitiveTypeSpecifier> expression_as_primitive =
					std::dynamic_pointer_cast<const PrimitiveTypeSpecifier>(
							expression_type_specifier);

			if (expression_as_primitive == nullptr
					|| !(expression_as_primitive->AnalyzeAssignmentTo(
							PrimitiveTypeSpecifier::GetInt(),
							context->GetTypeTable()))) {
				yy::location position = m_exit_expression->GetLocation();
				errors = ErrorList::From(
						make_shared<Error>(Error::SEMANTIC,
								Error::EXIT_STATUS_MUST_BE_AN_INTEGER,
								position.begin,
								expression_type_specifier->ToString()), errors);
			}
		}
	}

	return PreprocessResult(PreprocessResult::ReturnCoverage::NONE, errors);
}
Esempio n. 6
0
const_shared_ptr<Result> ComplexType::PreprocessSymbol(
		const std::shared_ptr<ExecutionContext> execution_context,
		const_shared_ptr<ComplexTypeSpecifier> type_specifier,
		const_shared_ptr<Expression> initializer) const {
	ErrorListRef errors = ErrorList::GetTerminator();

	plain_shared_ptr<void> value;
	plain_shared_ptr<Symbol> symbol = Symbol::GetDefaultSymbol();

	auto type_table = execution_context->GetTypeTable();
	if (initializer) {
		errors = initializer->Validate(execution_context);
		if (ErrorList::IsTerminator(errors)) {
			return PreprocessSymbolCore(execution_context, type_specifier,
					initializer);
		}
	} else {
		auto type_result = type_specifier->GetType(type_table);
		errors = type_result->GetErrors();
		if (ErrorList::IsTerminator(errors)) {
			auto type = type_result->GetData<TypeDefinition>();
			value = type->GetDefaultValue(type_table);
		}
	}

	if (ErrorList::IsTerminator(errors)) {
		//we've been able to get a good initial value (that is, no errors have occurred)
		symbol = GetSymbol(type_table, type_specifier, value);
	}

	return make_shared<Result>(symbol, errors);
}
Esempio n. 7
0
int SSL_shutdown(SSL* ssl)
{
    if (!ssl->GetQuietShutdown()) {
      Alert alert(warning, close_notify);
      sendAlert(*ssl, alert);
    }
    ssl->useLog().ShowTCP(ssl->getSocket().get_fd(), true);

    GetErrors().Remove();

    return SSL_SUCCESS;
}
Esempio n. 8
0
const ErrorListRef ComplexType::Instantiate(
		const std::shared_ptr<ExecutionContext> execution_context,
		const_shared_ptr<ComplexTypeSpecifier> type_specifier,
		const_shared_ptr<std::string> instance_name,
		const_shared_ptr<Expression> initializer) const {
	ErrorListRef errors = ErrorList::GetTerminator();
	SetResult set_result = SetResult::NO_SET_RESULT;
	yy::location location = GetDefaultLocation();
	plain_shared_ptr<TypeSpecifier> initializer_type_specifier = nullptr;
	if (initializer && !initializer->IsConstant()) {
		location = initializer->GetLocation();

		auto initializer_type_specifier_result = initializer->GetTypeSpecifier(
				execution_context);
		errors = initializer_type_specifier_result.GetErrors();
		if (ErrorList::IsTerminator(errors)) {
			auto initializer_type_specifier =
					initializer_type_specifier_result.GetData();
			auto result = initializer->Evaluate(execution_context,
					execution_context);
			errors = result->GetErrors();

			if (ErrorList::IsTerminator(errors)) {
				set_result = InstantiateCore(execution_context, type_specifier,
						initializer_type_specifier, *instance_name,
						result->GetData<void>());
			}
		}
	}

	if (set_result) {
		errors =
				ToErrorListRef(set_result, location, instance_name,
						execution_context->GetSymbol(*instance_name)->GetTypeSpecifier(),
						initializer_type_specifier); //initializer_type will be null if initializer is not set
	}

	return errors;
}
Esempio n. 9
0
const_shared_ptr<Result> FunctionDeclaration::FromTypeSpecifier(
		const FunctionTypeSpecifier& type_specifier,
		const TypeTable& type_table) {
	ErrorListRef errors = ErrorList::GetTerminator();

	TypeSpecifierListRef subject = type_specifier.GetParameterTypeList();
	DeclarationListRef result = DeclarationList::GetTerminator();
	int count = 1;
	while (!TypeSpecifierList::IsTerminator(subject)) {
		ostringstream buf;
		const_shared_ptr<TypeSpecifier> data = subject->GetData();
		buf << "Arg" << count;
		auto parameter_type_result = data->GetType(type_table);

		auto parameter_errors = parameter_type_result->GetErrors();
		if (ErrorList::IsTerminator(parameter_errors)) {
			auto parameter_type =
					parameter_type_result->GetData<TypeDefinition>();
			result = DeclarationList::From(
					parameter_type->GetDeclarationStatement(
							GetDefaultLocation(), data, GetDefaultLocation(),
							const_shared_ptr<string>(new string(buf.str())),
							GetDefaultLocation(), nullptr), result);
		} else {
			errors = ErrorList::Concatenate(errors, parameter_errors);
		}
		count++;
		subject = subject->GetNext();
	}

	plain_shared_ptr<FunctionDeclaration> declaration = nullptr;
	if (ErrorList::IsTerminator(errors)) {
		DeclarationListRef declaration_list = DeclarationList::Reverse(result);
		declaration = make_shared<FunctionDeclaration>(declaration_list,
				type_specifier.GetReturnTypeSpecifier(),
				type_specifier.GetLocation());
	}

	return make_shared<Result>(declaration, errors);
}
Esempio n. 10
0
const std::string MaybeType::ValueToString(const TypeTable& type_table,
		const Indent& indent, const_shared_ptr<void> value) const {
	ostringstream buffer;
	auto sum_instance = static_pointer_cast<const Sum>(value);
	auto tag = sum_instance->GetTag();
	buffer << "{" << *tag << "}";
	if (*tag == *TypeTable::GetNilName()) {
	} else if (*tag == *MaybeTypeSpecifier::VARIANT_NAME) {
		auto type_result = m_base_type_specifier->GetType(type_table, RESOLVE);
		if (ErrorList::IsTerminator(type_result->GetErrors())) {
			auto type = type_result->GetData<TypeDefinition>();
			auto inner_value = sum_instance->GetValue();
			buffer << type->GetValueSeparator(indent, inner_value.get());
			buffer << type->ValueToString(type_table, indent + 1, inner_value);
		} else {
			buffer << "<undefined type>";
		}
	} else {
		buffer << "<undefined variant>";
	}
	return buffer.str();
}
Esempio n. 11
0
TypedResult<string> OpenExpression::ToString(
		const shared_ptr<ExecutionContext> execution_context) const {
	ostringstream buf;
	buf << "open(";
	auto errors = ErrorList::GetTerminator();
	ArgumentListRef argument = GetArgumentListRef();
	while (!ArgumentList::IsTerminator(argument)) {
		auto argument_result = argument->GetData()->ToString(execution_context);
		errors = ErrorList::Concatenate(errors, argument_result.GetErrors());
		if (ErrorList::IsTerminator(errors)) {
			buf << *(argument_result.GetData());
			if (!ArgumentList::IsTerminator(argument->GetNext())) {
				buf << ",";
			}
		}

		argument = argument->GetNext();
	}
	buf << ")";
	return TypedResult<string>(const_shared_ptr<string>(new string(buf.str())),
			errors);
}
const ExecutionResult ComplexInstantiationStatement::Execute(
		const shared_ptr<ExecutionContext> context,
		const shared_ptr<ExecutionContext> closure) const {
	auto type_result = m_type_specifier->GetType(context->GetTypeTable(),
			RESOLVE);

	auto errors = type_result->GetErrors();
	if (ErrorList::IsTerminator(errors)) {
		auto type = type_result->GetData<TypeDefinition>();
		auto as_complex = dynamic_pointer_cast<const ComplexType>(type);
		if (as_complex) {
			errors = as_complex->Instantiate(context, m_type_specifier,
					GetName(), GetInitializerExpression());
		} else {
			//type does not exist
			errors = ErrorList::From(
					make_shared<Error>(Error::RUNTIME, Error::UNDECLARED_TYPE,
							m_type_specifier_location.begin,
							m_type_specifier->ToString()), errors);
		}
	}

	return ExecutionResult(errors);
}
Esempio n. 13
0
int Compile(KIMLBYTE *&code, KIMLUINT &codeSize)
{
	auto compiler = new Compiler();
	if (!compiler)
	{
		showError("Cannot initialize compiler service.\n");
		return RET_FAIL_COMPILER;
	}

	std::vector<std::string> files;
	for (auto it = includeFiles.begin(); it != includeFiles.end(); ++it)
	{
		files.push_back(*it);
	}
	files.push_back(inputfile);

	bool failed = false;

	FILE *fp;
	for (auto it = files.begin(); it != files.end(); ++it)
	{
		fp = fopen(it->c_str(), "r");
		if (!fp)
		{
			showError("Cannot open: %s.\n", it->c_str());
			delete compiler;
			return RET_FAIL_IO;
		}

		if (!compiler->Parse(it->c_str(), fp))
		{
			failed = true;
		}

		fclose(fp);
	}

	if (failed)
	{
		showError("*** Parsing failed.\n");
		delete compiler;
		return RET_FAIL_COMPILER;
	}

	if (!compiler->Compile(hasDebugInfo))
	{
		auto &errors = compiler->GetErrors();
		for (unsigned int i = 0, c = errors.size(); i < c; ++i)
		{
			auto &error = errors[i];
			KIMLCSTRING msg = compileErrorMessages[error.code];
			showError("%s[%u]: %s\n", files[error.compileUnitIndex].c_str(), error.line, msg);
		}
		delete compiler;
		return RET_FAIL_COMPILER;
	}

	if (!compiler->Finish())
	{
		showError("*** Failed to finish compilation.\n");
		delete compiler;
		return RET_FAIL_COMPILER;
	}

	if (!compiler->GetByteCode(&code, &codeSize))
	{
		showError("*** Failed to export bytecode.\n");
		delete compiler;
		return RET_FAIL_COMPILER;
	}

	delete compiler;
	return RET_OK;
}
Esempio n. 14
0
int SSL_clear(SSL* ssl)
{
    GetErrors().Remove();

    return SSL_SUCCESS;
}
Esempio n. 15
0
int SSL_accept(SSL* ssl)
{
    if (ssl->GetError() == YasslError(SSL_ERROR_WANT_READ))
        ssl->SetError(no_error);

    if (ssl->GetError() == YasslError(SSL_ERROR_WANT_WRITE)) {
    
        ssl->SetError(no_error);
        ssl->SendWriteBuffered();
        if (!ssl->GetError())
            ssl->useStates().UseAccept() =
                             AcceptState(ssl->getStates().GetAccept() + 1);
    }

    switch (ssl->getStates().GetAccept()) {

    case ACCEPT_BEGIN :
        processReply(*ssl);
        if (!ssl->GetError())
            ssl->useStates().UseAccept() = ACCEPT_FIRST_REPLY_DONE;

    case ACCEPT_FIRST_REPLY_DONE :
        sendServerHello(*ssl);

        if (!ssl->getSecurity().get_resuming()) {
            sendCertificate(*ssl);

            if (ssl->getSecurity().get_connection().send_server_key_)
                sendServerKeyExchange(*ssl);

            if(ssl->getCrypto().get_certManager().verifyPeer())
                sendCertificateRequest(*ssl);

            sendServerHelloDone(*ssl);
            ssl->flushBuffer();
        }
      
        if (!ssl->GetError())
            ssl->useStates().UseAccept() = SERVER_HELLO_DONE;

    case SERVER_HELLO_DONE :
        if (!ssl->getSecurity().get_resuming()) {
            while (ssl->getStates().getServer() < clientFinishedComplete) {
                if (ssl->GetError()) break;
                processReply(*ssl);
            }
        }
        if (!ssl->GetError())
            ssl->useStates().UseAccept() = ACCEPT_SECOND_REPLY_DONE;

    case ACCEPT_SECOND_REPLY_DONE :
        sendChangeCipher(*ssl);
        sendFinished(*ssl, server_end);
        ssl->flushBuffer();

        if (!ssl->GetError())
            ssl->useStates().UseAccept() = ACCEPT_FINISHED_DONE;

    case ACCEPT_FINISHED_DONE :
        if (ssl->getSecurity().get_resuming()) {
            while (ssl->getStates().getServer() < clientFinishedComplete) {
                if (ssl->GetError()) break;
                processReply(*ssl);
            }
        }
        if (!ssl->GetError())
            ssl->useStates().UseAccept() = ACCEPT_THIRD_REPLY_DONE;

    case ACCEPT_THIRD_REPLY_DONE :
        ssl->useLog().ShowTCP(ssl->getSocket().get_fd());

        if (ssl->GetError()) {
            GetErrors().Add(ssl->GetError());
            return SSL_FATAL_ERROR;
        }
        return SSL_SUCCESS;

    default:
        return SSL_FATAL_ERROR; // unknown state
    }
}
Esempio n. 16
0
// if you get an error from connect see note at top of README
int SSL_connect(SSL* ssl)
{
    if (ssl->GetError() == YasslError(SSL_ERROR_WANT_READ))
        ssl->SetError(no_error);

    if (ssl->GetError() == YasslError(SSL_ERROR_WANT_WRITE)) {
    
        ssl->SetError(no_error);
        ssl->SendWriteBuffered();
        if (!ssl->GetError())
            ssl->useStates().UseConnect() =
                             ConnectState(ssl->getStates().GetConnect() + 1);
    }

    ClientState neededState;

    switch (ssl->getStates().GetConnect()) {

    case CONNECT_BEGIN :
        sendClientHello(*ssl);
        if (!ssl->GetError())
            ssl->useStates().UseConnect() = CLIENT_HELLO_SENT;

    case CLIENT_HELLO_SENT :
        neededState = ssl->getSecurity().get_resuming() ?
                      serverFinishedComplete : serverHelloDoneComplete;
        while (ssl->getStates().getClient() < neededState) {
            if (ssl->GetError()) break;
            processReply(*ssl);
            // if resumption failed, reset needed state 
            if (neededState == serverFinishedComplete)
                if (!ssl->getSecurity().get_resuming())
                    neededState = serverHelloDoneComplete;
        }
        if (!ssl->GetError())
            ssl->useStates().UseConnect() = FIRST_REPLY_DONE;

    case FIRST_REPLY_DONE :
        if(ssl->getCrypto().get_certManager().sendVerify())
            sendCertificate(*ssl);

        if (!ssl->getSecurity().get_resuming())
            sendClientKeyExchange(*ssl);

        if(ssl->getCrypto().get_certManager().sendVerify())
            sendCertificateVerify(*ssl);

        sendChangeCipher(*ssl);
        sendFinished(*ssl, client_end);
        ssl->flushBuffer();

        if (!ssl->GetError())
            ssl->useStates().UseConnect() = FINISHED_DONE;

    case FINISHED_DONE :
        if (!ssl->getSecurity().get_resuming())
            while (ssl->getStates().getClient() < serverFinishedComplete) {
                if (ssl->GetError()) break;
                processReply(*ssl);
            }
        if (!ssl->GetError())
            ssl->useStates().UseConnect() = SECOND_REPLY_DONE;

    case SECOND_REPLY_DONE :
        ssl->verifyState(serverFinishedComplete);
        ssl->useLog().ShowTCP(ssl->getSocket().get_fd());

        if (ssl->GetError()) {
            GetErrors().Add(ssl->GetError());
            return SSL_FATAL_ERROR;
        }   
        return SSL_SUCCESS;

    default :
        return SSL_FATAL_ERROR; // unkown state
    }
}
Esempio n. 17
0
const ErrorListRef BinaryExpression::Validate(
		const shared_ptr<ExecutionContext> execution_context,
		const_shared_ptr<TypeSpecifier> valid_left,
		const_shared_ptr<TypeSpecifier> valid_right) const {
	ErrorListRef errors = ErrorList::GetTerminator();

	const OperatorType op = GetOperator();

	auto left = GetLeft();
	auto left_errors = left->Validate(execution_context);
	if (ErrorList::IsTerminator(left_errors)) {
		auto left_type_specifier_result = left->GetTypeSpecifier(
				execution_context);
		auto left_type_specifier_errors =
				left_type_specifier_result.GetErrors();
		if (ErrorList::IsTerminator(left_type_specifier_errors)) {
			auto left_type_specifier = left_type_specifier_result.GetData();
			auto left_analysis = left_type_specifier->AnalyzeAssignmentTo(
					valid_left, execution_context->GetTypeTable());
			if (left_analysis != EQUIVALENT && left_analysis != UNAMBIGUOUS) {
				errors = ErrorList::From(
						make_shared<Error>(Error::SEMANTIC,
								Error::INVALID_LEFT_OPERAND_TYPE,
								left->GetLocation().begin,
								OperatorToString(op)), errors);
			}
		} else {
			errors = ErrorList::Concatenate(errors, left_type_specifier_errors);
		}
	} else {
		errors = ErrorList::Concatenate(errors, left_errors);
	}

	auto right = GetRight();
	auto right_errors = right->Validate(execution_context);
	if (ErrorList::IsTerminator(right_errors)) {
		auto right_type_specifier_result = GetRight()->GetTypeSpecifier(
				execution_context);
		auto right_type_specifier_errors =
				right_type_specifier_result.GetErrors();
		if (ErrorList::IsTerminator(right_type_specifier_errors)) {
			auto right_type_specifier = right_type_specifier_result.GetData();
			auto right_analysis = right_type_specifier->AnalyzeAssignmentTo(
					valid_right, execution_context->GetTypeTable());
			if (right_analysis != EQUIVALENT && right_analysis != UNAMBIGUOUS) {
				errors = ErrorList::From(
						make_shared<Error>(Error::SEMANTIC,
								Error::INVALID_RIGHT_OPERAND_TYPE,
								right->GetLocation().begin,
								OperatorToString(op)), errors);
			}
		} else {
			errors = ErrorList::Concatenate(errors,
					right_type_specifier_errors);
		}
	} else {
		errors = ErrorList::Concatenate(errors, right_errors);
	}

	return errors;
}
Esempio n. 18
0
const_shared_ptr<Result> BinaryExpression::Evaluate(
		const shared_ptr<ExecutionContext> context,
		const shared_ptr<ExecutionContext> closure) const {
	ErrorListRef errors = ErrorList::GetTerminator();
	const_shared_ptr<Expression> left = GetLeft();
	const_shared_ptr<Expression> right = GetRight();

	const_shared_ptr<Result> left_result = left->Evaluate(context, closure);
	if (!ErrorList::IsTerminator(left_result->GetErrors())) {
		return left_result;
	}

	const_shared_ptr<Result> right_result = right->Evaluate(context, closure);
	if (!ErrorList::IsTerminator(right_result->GetErrors())) {
		return right_result;
	}

	auto left_type_specifier_result = left->GetTypeSpecifier(context);
	auto right_type_specifier_result = right->GetTypeSpecifier(context);

	errors = left_type_specifier_result.GetErrors();
	if (ErrorList::IsTerminator(errors)) {
		errors = right_type_specifier_result.GetErrors();
		if (ErrorList::IsTerminator(errors)) {
			yy::location left_position = left->GetLocation();
			yy::location right_position = right->GetLocation();

			auto type_table = context->GetTypeTable();

			auto left_type = left_type_specifier_result.GetData();
			auto right_type = right_type_specifier_result.GetData();

			// This logic is essentially a big muxer.
			// It works in tandem with C++ type widening to convert operands to the same data type
			if (left_type->AnalyzeAssignmentTo(
					PrimitiveTypeSpecifier::GetBoolean(), type_table)
					== EQUIVALENT) {
				bool left_value = *(left_result->GetData<bool>());

				if (right_type->AnalyzeAssignmentTo(
						PrimitiveTypeSpecifier::GetBoolean(), type_table)
						== EQUIVALENT) {
					bool right_value = *(right_result->GetData<bool>());
					return compute(left_value, right_value, left_position,
							right_position);
				} else if (right_type->AnalyzeAssignmentTo(
						PrimitiveTypeSpecifier::GetByte(), type_table)
						== EQUIVALENT) {
					auto right_value = *(right_result->GetData<std::uint8_t>());
					return compute(left_value, right_value, left_position,
							right_position);
				} else if (right_type->AnalyzeAssignmentTo(
						PrimitiveTypeSpecifier::GetInt(), type_table)
						== EQUIVALENT) {
					int right_value = *(right_result->GetData<int>());
					return compute(left_value, right_value, left_position,
							right_position);
				} else if (right_type->AnalyzeAssignmentTo(
						PrimitiveTypeSpecifier::GetDouble(), type_table)
						== EQUIVALENT) {
					double right_value = *(right_result->GetData<double>());
					return compute(left_value, right_value, left_position,
							right_position);
				} else if (right_type->AnalyzeAssignmentTo(
						PrimitiveTypeSpecifier::GetString(), type_table)
						== EQUIVALENT) {
					string right_value = *(right_result->GetData<string>());
					return compute(left_value, right_value, left_position,
							right_position);
				} else {
					assert(false);
				}
			} else if (left_type->AnalyzeAssignmentTo(
					PrimitiveTypeSpecifier::GetByte(), type_table)
					== EQUIVALENT) {
				auto left_value = *(left_result->GetData<std::uint8_t>());

				if (right_type->AnalyzeAssignmentTo(
						PrimitiveTypeSpecifier::GetBoolean(), type_table)
						== EQUIVALENT) {
					bool right_value = *(right_result->GetData<bool>());
					return compute(left_value, right_value, left_position,
							right_position);
				} else if (right_type->AnalyzeAssignmentTo(
						PrimitiveTypeSpecifier::GetByte(), type_table)
						== EQUIVALENT) {
					auto right_value = *(right_result->GetData<std::uint8_t>());
					return compute(left_value, right_value, left_position,
							right_position);
				} else if (right_type->AnalyzeAssignmentTo(
						PrimitiveTypeSpecifier::GetInt(), type_table)
						== EQUIVALENT) {
					int right_value = *(right_result->GetData<int>());
					return compute(left_value, right_value, left_position,
							right_position);
				} else if (right_type->AnalyzeAssignmentTo(
						PrimitiveTypeSpecifier::GetDouble(), type_table)
						== EQUIVALENT) {
					double right_value = *(right_result->GetData<double>());
					return compute(left_value, right_value, left_position,
							right_position);
				} else if (right_type->AnalyzeAssignmentTo(
						PrimitiveTypeSpecifier::GetString(), type_table)
						== EQUIVALENT) {
					string right_value = *(right_result->GetData<string>());
					return compute(left_value, right_value, left_position,
							right_position);
				} else {
					assert(false);
				}
			} else if (left_type->AnalyzeAssignmentTo(
					PrimitiveTypeSpecifier::GetInt(), type_table)
					== EQUIVALENT) {
				int left_value = *(left_result->GetData<int>());

				if (right_type->AnalyzeAssignmentTo(
						PrimitiveTypeSpecifier::GetBoolean(), type_table)
						== EQUIVALENT) {
					bool right_value = *(right_result->GetData<bool>());
					return compute(left_value, right_value, left_position,
							right_position);
				} else if (right_type->AnalyzeAssignmentTo(
						PrimitiveTypeSpecifier::GetByte(), type_table)
						== EQUIVALENT) {
					auto right_value = *(right_result->GetData<std::uint8_t>());
					return compute(left_value, right_value, left_position,
							right_position);
				} else if (right_type->AnalyzeAssignmentTo(
						PrimitiveTypeSpecifier::GetInt(), type_table)
						== EQUIVALENT) {
					int right_value = *(right_result->GetData<int>());
					return compute(left_value, right_value, left_position,
							right_position);
				} else if (right_type->AnalyzeAssignmentTo(
						PrimitiveTypeSpecifier::GetDouble(), type_table)
						== EQUIVALENT) {
					double right_value = *(right_result->GetData<double>());
					return compute(left_value, right_value, left_position,
							right_position);
				} else if (right_type->AnalyzeAssignmentTo(
						PrimitiveTypeSpecifier::GetString(), type_table)
						== EQUIVALENT) {
					string right_value = *(right_result->GetData<string>());
					return compute(left_value, right_value, left_position,
							right_position);
				} else {
					assert(false);
				}
			} else if (left_type->AnalyzeAssignmentTo(
					PrimitiveTypeSpecifier::GetDouble(), type_table)
					== EQUIVALENT) {
				double left_value = *(left_result->GetData<double>());

				if (right_type->AnalyzeAssignmentTo(
						PrimitiveTypeSpecifier::GetBoolean(), type_table)
						== EQUIVALENT) {
					bool right_value = *(right_result->GetData<bool>());
					return compute(left_value, right_value, left_position,
							right_position);
				} else if (right_type->AnalyzeAssignmentTo(
						PrimitiveTypeSpecifier::GetByte(), type_table)
						== EQUIVALENT) {
					auto right_value = *(right_result->GetData<std::uint8_t>());
					return compute(left_value, right_value, left_position,
							right_position);
				} else if (right_type->AnalyzeAssignmentTo(
						PrimitiveTypeSpecifier::GetInt(), type_table)
						== EQUIVALENT) {
					int right_value = *(right_result->GetData<int>());
					return compute(left_value, right_value, left_position,
							right_position);
				} else if (right_type->AnalyzeAssignmentTo(
						PrimitiveTypeSpecifier::GetDouble(), type_table)
						== EQUIVALENT) {
					double right_value = *(right_result->GetData<double>());
					return compute(left_value, right_value, left_position,
							right_position);
				} else if (right_type->AnalyzeAssignmentTo(
						PrimitiveTypeSpecifier::GetString(), type_table)
						== EQUIVALENT) {
					string right_value = *(right_result->GetData<string>());
					return compute(left_value, right_value, left_position,
							right_position);
				} else {
					assert(false);
				}
			} else if (left_type->AnalyzeAssignmentTo(
					PrimitiveTypeSpecifier::GetString(), type_table)
					== EQUIVALENT) {
				string left_value = *(left_result->GetData<string>());

				if (right_type->AnalyzeAssignmentTo(
						PrimitiveTypeSpecifier::GetBoolean(), type_table)
						== EQUIVALENT) {
					bool right_value = *(right_result->GetData<bool>());
					return compute(left_value, right_value, left_position,
							right_position);
				} else if (right_type->AnalyzeAssignmentTo(
						PrimitiveTypeSpecifier::GetByte(), type_table)
						== EQUIVALENT) {
					auto right_value = *(right_result->GetData<std::uint8_t>());
					return compute(left_value, right_value, left_position,
							right_position);
				} else if (right_type->AnalyzeAssignmentTo(
						PrimitiveTypeSpecifier::GetInt(), type_table)
						== EQUIVALENT) {
					int right_value = *(right_result->GetData<int>());
					return compute(left_value, right_value, left_position,
							right_position);
				} else if (right_type->AnalyzeAssignmentTo(
						PrimitiveTypeSpecifier::GetDouble(), type_table)
						== EQUIVALENT) {
					double right_value = *(right_result->GetData<double>());
					return compute(left_value, right_value, left_position,
							right_position);
				} else if (right_type->AnalyzeAssignmentTo(
						PrimitiveTypeSpecifier::GetString(), type_table)
						== EQUIVALENT) {
					string right_value = *(right_result->GetData<string>());
					return compute(left_value, right_value, left_position,
							right_position);
				} else {
					assert(false);
				}
			} else {
				assert(false);
			}
		}
	}

	return make_shared<Result>(nullptr, errors);
}
Esempio n. 19
0
const_shared_ptr<Result> OpenExpression::Evaluate(
		const shared_ptr<ExecutionContext> context,
		const shared_ptr<ExecutionContext> closure) const {
	// need to handle in-band errors
	// return file handle
	// return platform-dependent error codes; should handle mapping to platform-independent codes in std lib.

	// we assume that our validation pass caught any argument length issues
	auto path_argument_expression = GetArgumentListRef()->GetData();
	auto path_argument_evaluation = path_argument_expression->Evaluate(context,
			closure);

	auto index = 0;
	auto result_code = 0;
	auto result_message = make_shared<string>();
	auto errors = path_argument_evaluation->GetErrors();
	if (ErrorList::IsTerminator(errors)) {
		auto path = path_argument_evaluation->GetData<string>();
		auto mode_argument_expression =
				GetArgumentListRef()->GetNext()->GetData();
		auto mode_argument_evaluation = mode_argument_expression->Evaluate(
				context, closure);

		errors = mode_argument_evaluation->GetErrors();
		if (ErrorList::IsTerminator(errors)) {
			std::ios::openmode open_mode = std::ios::openmode();
			auto mode_definition =
					mode_argument_evaluation->GetData<Record>()->GetDefinition();

			if (*static_pointer_cast<const bool>(
					mode_definition->GetSymbol(*Builtins::STREAM_MODE_IN_NAME)->GetValue())
					== true) {
				open_mode = open_mode | std::ios::in;
			}

			if (*static_pointer_cast<const bool>(
					mode_definition->GetSymbol(*Builtins::STREAM_MODE_OUT_NAME)->GetValue())
					== true) {
				open_mode = open_mode | std::ios::out;
			}

			if (*static_pointer_cast<const bool>(
					mode_definition->GetSymbol(
							*Builtins::STREAM_MODE_BINARY_NAME)->GetValue())
					== true) {
				open_mode = open_mode | std::ios::binary;
			}

			if (*static_pointer_cast<const bool>(
					mode_definition->GetSymbol(*Builtins::STREAM_MODE_ATE_NAME)->GetValue())
					== true) {
				open_mode = open_mode | std::ios::ate;
			}

			if (*static_pointer_cast<const bool>(
					mode_definition->GetSymbol(*Builtins::STREAM_MODE_APP_NAME)->GetValue())
					== true) {
				open_mode = open_mode | std::ios::app;
			}

			if (*static_pointer_cast<const bool>(
					mode_definition->GetSymbol(
							*Builtins::STREAM_MODE_TRUNC_NAME)->GetValue())
					== true) {
				open_mode = open_mode | std::ios::trunc;
			}

			auto stream = make_shared<fstream>();
			stream->exceptions(std::ifstream::failbit | std::ifstream::badbit);
			try {
				stream->open(*path, open_mode);
				// add stream to file handle list
				// N.B. that this process is not synchronized
				index = Builtins::get_file_handle_map()->size();
				Builtins::get_file_handle_map()->insert(
						std::pair<int, volatile_shared_ptr<fstream>>(index,
								stream));
			} catch (std::fstream::failure &e) {
				result_code = errno;
				result_message = make_shared<string>(
						std::strerror(result_code));
			}
		}
	}

	auto type_table = closure->GetTypeTable();
	auto error_list_type_result =
			Builtins::get_error_list_type_specifier()->GetType(type_table,
					RETURN);
	assert(ErrorList::IsTerminator(error_list_type_result->GetErrors()));
	auto error_list_type = error_list_type_result->GetData<TypeDefinition>();

	if (result_code == 0) {
		auto result = make_shared<Sum>(Builtins::INT_RESULT_DATA_NAME,
				make_shared<int>(index));

		return make_shared<Result>(result, errors);
	} else {
		auto error_symbol_map = make_shared<symbol_map>();
		auto insert_result = error_symbol_map->insert(
				std::pair<const string, const_shared_ptr<Symbol>>(
						*Builtins::ERROR_CODE_NAME,
						make_shared<Symbol>(make_shared<int>(result_code))));
		assert(insert_result.second);
		insert_result = error_symbol_map->insert(
				std::pair<const string, const_shared_ptr<Symbol>>(
						*Builtins::ERROR_MESSAGE_NAME,
						make_shared<Symbol>(result_message)));
		assert(insert_result.second);
		auto error_symbol_table = make_shared<SymbolTable>(Modifier::Type::NONE,
				error_symbol_map);
		auto error = make_shared<Record>(error_symbol_table);

		auto error_list_symbol_map = make_shared<symbol_map>();
		insert_result = error_list_symbol_map->insert(
				std::pair<const string, const_shared_ptr<Symbol>>(
						*Builtins::ERROR_LIST_DATA_NAME,
						make_shared<Symbol>(
								Builtins::get_error_type_specifier(), error)));
		assert(insert_result.second);

		auto terminator = static_pointer_cast<const Record>(
				error_list_type->GetDefaultValue(type_table));
		auto error_list_sum = make_shared<Sum>(TypeTable::GetNilName(),
				terminator);
		insert_result = error_list_symbol_map->insert(
				std::pair<const string, const_shared_ptr<Symbol>>(
						*Builtins::ERROR_LIST_NEXT_NAME,
						make_shared<Symbol>(
								Builtins::get_error_list_maybe_type_specifier(),
								error_list_sum)));
		assert(insert_result.second);

		auto error_list_symbol_table = make_shared<SymbolTable>(
				Modifier::Type::NONE, error_list_symbol_map);
		auto error_list = make_shared<Record>(error_list_symbol_table);

		auto result = make_shared<Sum>(Builtins::INT_RESULT_ERRORS_NAME,
				error_list);
		return make_shared<Result>(result, errors);
	}
}
Esempio n. 20
0
const ErrorListRef OpenExpression::Validate(
		const shared_ptr<ExecutionContext> execution_context) const {
	// check argument count
	auto errors = ErrorList::GetTerminator();
	auto type_table = execution_context->GetTypeTable();

	uint arg_count = 0;
	ArgumentListRef argument = GetArgumentListRef();
	while (!ArgumentList::IsTerminator(argument)) {
		auto argument_subject = argument->GetData();
		auto validation = argument_subject->Validate(execution_context);
		errors = ErrorList::Concatenate(errors, validation);

		if (ErrorList::IsTerminator(errors)) {
			auto argument_type_specifier_result =
					argument_subject->GetTypeSpecifier(execution_context);

			errors = ErrorList::Concatenate(errors,
					argument_type_specifier_result.GetErrors());
			if (ErrorList::IsTerminator(errors)) {
				auto argument_type_specifier =
						argument_type_specifier_result.GetData();

				if (arg_count == 0) {
					auto specifier = PrimitiveTypeSpecifier::GetString();
					auto assignability =
							argument_type_specifier->AnalyzeAssignmentTo(
									specifier, type_table);
					if (assignability == AnalysisResult::AMBIGUOUS) {
						errors =
								ErrorList::From(
										make_shared<Error>(Error::SEMANTIC,
												Error::AMBIGUOUS_WIDENING_CONVERSION,
												argument_type_specifier->GetLocation().begin,
												argument_type_specifier->ToString(),
												specifier->ToString()), errors);
					} else if (assignability == INCOMPATIBLE) {
						errors =
								ErrorList::From(
										make_shared<Error>(Error::SEMANTIC,
												Error::ASSIGNMENT_TYPE_ERROR,
												argument_type_specifier->GetLocation().begin,
												argument_type_specifier->ToString(),
												specifier->ToString()), errors);
					}
				} else if (arg_count == 1) {
					auto specifier = Builtins::get_stream_mode_type_specifier();
					auto assignability =
							argument_type_specifier->AnalyzeAssignmentTo(
									specifier, type_table);
					if (assignability == AnalysisResult::AMBIGUOUS) {
						errors =
								ErrorList::From(
										make_shared<Error>(Error::SEMANTIC,
												Error::AMBIGUOUS_WIDENING_CONVERSION,
												argument_type_specifier->GetLocation().begin,
												argument_type_specifier->ToString(),
												specifier->ToString()), errors);
					} else if (assignability == INCOMPATIBLE) {
						errors =
								ErrorList::From(
										make_shared<Error>(Error::SEMANTIC,
												Error::ASSIGNMENT_TYPE_ERROR,
												argument_type_specifier->GetLocation().begin,
												argument_type_specifier->ToString(),
												specifier->ToString()), errors);
					}
				} else {
					// too many arguments
					errors = ErrorList::From(
							make_shared<Error>(Error::SEMANTIC,
									Error::TOO_MANY_ARGUMENTS,
									argument_subject->GetLocation().begin,
									"(string, stream_mode) -> int_result"),
							errors);
					break;
				}
			}
		}

		arg_count++;
		argument = argument->GetNext();
	}

	if (arg_count == 0) {
		errors = ErrorList::From(
				make_shared<Error>(Error::SEMANTIC, Error::NO_PARAMETER_DEFAULT,
						GetArgumentListRefLocation().end, "path"),
				errors);
	}

	if (arg_count == 1) {
		errors = ErrorList::From(
				make_shared<Error>(Error::SEMANTIC, Error::NO_PARAMETER_DEFAULT,
						GetArgumentListRefLocation().end, "mode"), errors);
	}

	return errors;
}
Esempio n. 21
0
	IResultPtr result() const
	{
		auto output = join(GetOutput());
		auto errors = join(GetErrors());
		return IResultPtr(new PerforceResult(output.c_str(), errors.c_str(), fileResults()));
	}