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); }
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; }
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()); }
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); }
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); }
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; }
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; }
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); }
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(); }
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); }
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; }
int SSL_clear(SSL* ssl) { GetErrors().Remove(); return SSL_SUCCESS; }
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 } }
// 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 } }
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; }
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); }
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); } }
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; }
IResultPtr result() const { auto output = join(GetOutput()); auto errors = join(GetErrors()); return IResultPtr(new PerforceResult(output.c_str(), errors.c_str(), fileResults())); }