blob: ccee19806f6e30a7b59ac5664f3291e29222c4a9 [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/developer/shell/interpreter/src/server.h"
#include <lib/syslog/cpp/macros.h>
#include <memory>
#include <string_view>
#include "lib/async-loop/default.h"
#include "lib/fidl-async/cpp/bind.h"
#include "lib/svc/dir.h"
#include "src/developer/shell/console/ast_builder.h"
#include "src/developer/shell/interpreter/src/expressions.h"
#include "src/developer/shell/interpreter/src/instructions.h"
#include "src/developer/shell/interpreter/src/schema.h"
#include "src/developer/shell/interpreter/src/types.h"
#include "zircon/process.h"
#include "zircon/processargs.h"
#include "zircon/status.h"
namespace shell {
namespace interpreter {
namespace server {
inline std::string_view GetView(const ::fidl::StringView& view) {
return std::string_view(view.data(), view.size());
}
std::unique_ptr<Type> GetType(ServerInterpreterContext* context, uint64_t node_file_id,
uint64_t node_node_id,
const llcpp::fuchsia::shell::ShellType& shell_type) {
if (shell_type.is_undef()) {
return std::make_unique<TypeUndefined>();
}
if (shell_type.is_builtin_type()) {
switch (shell_type.builtin_type()) {
case llcpp::fuchsia::shell::BuiltinType::BOOL:
return std::make_unique<TypeBool>();
case llcpp::fuchsia::shell::BuiltinType::CHAR:
return std::make_unique<TypeChar>();
case llcpp::fuchsia::shell::BuiltinType::STRING:
return std::make_unique<TypeString>();
case llcpp::fuchsia::shell::BuiltinType::INT8:
return std::make_unique<TypeInt8>();
case llcpp::fuchsia::shell::BuiltinType::UINT8:
return std::make_unique<TypeUint8>();
case llcpp::fuchsia::shell::BuiltinType::INT16:
return std::make_unique<TypeInt16>();
case llcpp::fuchsia::shell::BuiltinType::UINT16:
return std::make_unique<TypeUint16>();
case llcpp::fuchsia::shell::BuiltinType::INT32:
return std::make_unique<TypeInt32>();
case llcpp::fuchsia::shell::BuiltinType::UINT32:
return std::make_unique<TypeUint32>();
case llcpp::fuchsia::shell::BuiltinType::INT64:
return std::make_unique<TypeInt64>();
case llcpp::fuchsia::shell::BuiltinType::UINT64:
return std::make_unique<TypeUint64>();
case llcpp::fuchsia::shell::BuiltinType::INTEGER:
return std::make_unique<TypeInteger>();
case llcpp::fuchsia::shell::BuiltinType::FLOAT32:
return std::make_unique<TypeFloat32>();
case llcpp::fuchsia::shell::BuiltinType::FLOAT64:
return std::make_unique<TypeFloat64>();
default:
break;
}
}
if (shell_type.is_object_schema()) {
NodeId node_id(shell_type.object_schema().file_id, shell_type.object_schema().node_id);
std::shared_ptr<ObjectSchema> schema_node =
context->execution_context()->interpreter()->GetObjectSchema(node_id);
if (schema_node == nullptr) {
context->execution_context()->EmitError(NodeId(node_file_id, node_node_id),
"Type not found for object");
return std::make_unique<TypeUndefined>();
}
return ObjectSchema::GetType(schema_node);
}
context->execution_context()->EmitError(NodeId(node_file_id, node_node_id), "Bad type.");
return std::make_unique<TypeUndefined>();
}
// - ServerInterpreterContext ----------------------------------------------------------------------
std::unique_ptr<Expression> ServerInterpreterContext::GetExpression(const NodeId& node_id) {
auto result = expressions_.find(node_id);
if (result == expressions_.end()) {
return nullptr;
}
auto returned_value = std::move(result->second);
FX_DCHECK(returned_value != nullptr);
expressions_.erase(result);
return returned_value;
}
// Return the schema declared by the given node id.
std::shared_ptr<ObjectSchema> ServerInterpreterContext::GetObjectSchema(const NodeId& node_id) {
auto result = object_schemas_.find(node_id);
if (result == object_schemas_.end()) {
return nullptr;
}
auto returned_value = std::move(result->second);
FX_DCHECK(returned_value != nullptr);
return returned_value;
}
// Retrieves the field corresponding to the given node id.
std::unique_ptr<ObjectDeclarationField> ServerInterpreterContext::GetObjectField(
const NodeId& node_id) {
auto result = fields_.find(node_id);
if (result == fields_.end()) {
return nullptr;
}
auto returned_value = std::move(result->second);
FX_DCHECK(returned_value != nullptr);
return returned_value;
}
// Retrieves the schema of the field definition for the given node id.
std::shared_ptr<ObjectFieldSchema> ServerInterpreterContext::GetObjectFieldSchema(
const NodeId& node_id) {
auto result = object_field_schemas_.find(node_id);
if (result == object_field_schemas_.end()) {
return nullptr;
}
auto returned_value = std::move(result->second);
FX_DCHECK(returned_value != nullptr);
return returned_value;
}
// - ServerInterpreter -----------------------------------------------------------------------------
void ServerInterpreter::EmitError(ExecutionContext* context, std::string error_message) {
service_->OnError((context == nullptr) ? 0 : context->id(), std::move(error_message));
if (context != nullptr) {
context->set_has_errors();
}
}
void ServerInterpreter::EmitError(ExecutionContext* context, NodeId node_id,
std::string error_message) {
FX_DCHECK(context != nullptr);
std::vector<llcpp::fuchsia::shell::Location> locations;
llcpp::fuchsia::shell::NodeId fidl_node_id{.file_id = node_id.file_id,
.node_id = node_id.node_id};
auto builder = llcpp::fuchsia::shell::Location::UnownedBuilder().set_node_id(
fidl::unowned_ptr(&fidl_node_id));
locations.emplace_back(builder.build());
service_->OnError(context->id(), locations, std::move(error_message));
context->set_has_errors();
}
void ServerInterpreter::DumpDone(ExecutionContext* context) {
FX_DCHECK(context != nullptr);
service_->OnDumpDone(context->id());
}
void ServerInterpreter::ContextDone(ExecutionContext* context) {
FX_DCHECK(context != nullptr);
service_->OnExecutionDone(context->id(), llcpp::fuchsia::shell::ExecuteResult::OK);
}
void ServerInterpreter::ContextDoneWithAnalysisError(ExecutionContext* context) {
FX_DCHECK(context != nullptr);
service_->OnExecutionDone(context->id(), llcpp::fuchsia::shell::ExecuteResult::ANALYSIS_ERROR);
}
void ServerInterpreter::ContextDoneWithExecutionError(ExecutionContext* context) {
FX_DCHECK(context != nullptr);
service_->OnExecutionDone(context->id(), llcpp::fuchsia::shell::ExecuteResult::EXECUTION_ERROR);
}
void ServerInterpreter::TextResult(ExecutionContext* context, std::string_view text) {
constexpr size_t kMaxResultSize = 65400;
size_t offset = 0;
while (text.size() - offset > kMaxResultSize) {
service_->OnTextResult(context->id(), std::string(text.data() + offset, kMaxResultSize),
/*partial_result=*/true);
offset += kMaxResultSize;
}
service_->OnTextResult(context->id(), std::string(text.data() + offset, text.size() - offset),
/*partial_result=*/false);
}
void ServerInterpreter::CreateServerContext(ExecutionContext* context) {
FX_DCHECK(contexts_.find(context->id()) == contexts_.end());
contexts_.emplace(context->id(), std::make_unique<ServerInterpreterContext>(context));
}
void ServerInterpreter::AddExpression(ServerInterpreterContext* context,
std::unique_ptr<Expression> expression, bool root_node) {
if (root_node) {
EmitError(context->execution_context(),
"Node " + expression->StringId() + " can't be a root node.");
return;
}
context->AddExpression(std::move(expression));
}
void ServerInterpreter::AddInstruction(ServerInterpreterContext* context,
std::unique_ptr<Instruction> instruction, bool root_node) {
if (root_node) {
context->execution_context()->AddPendingInstruction(std::move(instruction));
} else {
context->AddInstruction(std::move(instruction));
}
}
void ServerInterpreter::AddObjectSchema(ServerInterpreterContext* context,
std::shared_ptr<ObjectSchema> definition, bool root_node) {
if (root_node) {
context->execution_context()->interpreter()->AddObjectSchema(definition);
} else {
context->AddObjectSchema(definition);
}
}
void ServerInterpreter::AddObjectFieldSchema(ServerInterpreterContext* context,
std::shared_ptr<ObjectFieldSchema> definition,
bool root_node) {
if (root_node) {
EmitError(context->execution_context(),
"Node " + definition->StringId() + " can't be a root node.");
return;
}
context->AddObjectFieldSchema(definition);
}
void ServerInterpreter::AddObjectField(ServerInterpreterContext* context,
std::unique_ptr<ObjectDeclarationField> definition,
bool root_node) {
if (root_node) {
EmitError(context->execution_context(),
"Node " + definition->StringId() + " can't be a root node.");
return;
}
context->AddObjectField(std::move(definition));
}
std::unique_ptr<Expression> ServerInterpreter::GetNullableExpression(
ServerInterpreterContext* context, const NodeId& node_id) {
if (node_id.node_id == 0) {
return nullptr;
}
auto result = context->GetExpression(node_id);
if (result == nullptr) {
EmitError(context->execution_context(), "Can't find node " + node_id.StringId());
return nullptr;
}
return result;
}
std::unique_ptr<Expression> ServerInterpreter::GetExpression(ServerInterpreterContext* context,
const NodeId& container_id,
const std::string& member,
const NodeId& node_id) {
if (node_id.node_id == 0) {
EmitError(context->execution_context(), container_id, member + " can't be null.");
return nullptr;
}
auto result = context->GetExpression(node_id);
if (result == nullptr) {
EmitError(context->execution_context(), container_id,
"Can't find node " + node_id.StringId() + " for " + member + ".");
return nullptr;
}
return result;
}
std::shared_ptr<ObjectSchema> ServerInterpreter::GetObjectSchema(ServerInterpreterContext* context,
const NodeId& node_id) {
if (node_id.node_id == 0) {
return nullptr;
}
auto result = context->GetObjectSchema(node_id);
if (result == nullptr) {
EmitError(context->execution_context(), "Can't find schema node " + node_id.StringId());
return nullptr;
}
return result;
}
std::shared_ptr<ObjectFieldSchema> ServerInterpreter::GetObjectFieldSchema(
ServerInterpreterContext* context, const NodeId& node_id) {
if (node_id.node_id == 0) {
return nullptr;
}
auto result = context->GetObjectFieldSchema(node_id);
if (result == nullptr) {
EmitError(context->execution_context(), "Can't find node " + node_id.StringId());
return nullptr;
}
return result;
}
// - connect ---------------------------------------------------------------------------------------
void connect(void* untyped_context, const char* service_name, zx_handle_t service_request) {
auto server = static_cast<Server*>(untyped_context);
server->IncomingConnection(service_request);
}
// - Service ---------------------------------------------------------------------------------------
void Service::CreateExecutionContext(uint64_t context_id,
CreateExecutionContextCompleter::Sync completer) {
auto context = interpreter_->AddContext(context_id);
if (context != nullptr) {
interpreter_->CreateServerContext(context);
}
}
void Service::AddNodes(uint64_t context_id,
::fidl::VectorView<::llcpp::fuchsia::shell::NodeDefinition> nodes,
AddNodesCompleter::Sync _completer) {
auto context = interpreter_->GetServerContext(context_id);
if (context == nullptr) {
interpreter_->EmitError(nullptr,
"Execution context " + std::to_string(context_id) + " not defined.");
} else {
for (const auto& node : nodes) {
if (node.node.is_integer_literal()) {
AddIntegerLiteral(context, node.node_id.file_id, node.node_id.node_id,
node.node.integer_literal(), node.root_node);
} else if (node.node.is_variable_definition()) {
AddVariableDefinition(context, node.node_id.file_id, node.node_id.node_id,
node.node.variable_definition(), node.root_node);
} else if (node.node.is_object_schema()) {
AddObjectSchema(context, node.node_id.file_id, node.node_id.node_id,
node.node.object_schema(), node.root_node);
} else if (node.node.is_field_schema()) {
AddObjectSchemaField(context, node.node_id.file_id, node.node_id.node_id,
node.node.field_schema(), node.root_node);
} else if (node.node.is_object()) {
AddObject(context, node.node_id.file_id, node.node_id.node_id, node.node.object(),
node.root_node);
} else if (node.node.is_object_field()) {
AddObjectField(context, node.node_id.file_id, node.node_id.node_id,
node.node.object_field(), node.root_node);
} else if (node.node.is_string_literal()) {
AddStringLiteral(context, node.node_id.file_id, node.node_id.node_id,
node.node.string_literal(), node.root_node);
} else if (node.node.is_variable()) {
AddVariable(context, node.node_id.file_id, node.node_id.node_id, node.node.variable(),
node.root_node);
} else if (node.node.is_addition()) {
AddAddition(context, node.node_id.file_id, node.node_id.node_id, node.node.addition(),
node.root_node);
} else {
interpreter_->EmitError(context->execution_context(),
"Can't create node " + std::to_string(node.node_id.file_id) + ":" +
std::to_string(node.node_id.node_id) + " (unknown type).");
}
}
}
}
void Service::DumpExecutionContext(uint64_t context_id,
ExecuteExecutionContextCompleter::Sync completer) {
auto context = interpreter_->GetServerContext(context_id);
if (context == nullptr) {
interpreter_->EmitError(nullptr,
"Execution context " + std::to_string(context_id) + " not defined.");
} else {
context->execution_context()->Dump();
}
}
void Service::ExecuteExecutionContext(uint64_t context_id,
ExecuteExecutionContextCompleter::Sync completer) {
auto context = interpreter_->GetServerContext(context_id);
if (context == nullptr) {
interpreter_->EmitError(nullptr,
"Execution context " + std::to_string(context_id) + " not defined.");
} else {
if (context->PendingNodes()) {
interpreter_->EmitError(
context->execution_context(),
"Pending AST nodes for execution context " + std::to_string(context_id) + ".");
}
context->execution_context()->Execute();
interpreter_->EraseServerContext(context_id);
}
}
class LoadGlobalHelper {
public:
LoadGlobalHelper() = default;
fidl::VectorView<llcpp::fuchsia::shell::Node> nodes() { return builder_.NodesAsVectorView(); }
struct TypeAndValue {
shell::console::AstBuilder::NodeId value_id;
llcpp::fuchsia::shell::ShellType type;
};
TypeAndValue Set(const Value& value) {
TypeAndValue id;
switch (value.type()) {
case ValueType::kUndef: {
id.value_id.file_id = -1;
id.value_id.node_id = -1;
fidl::aligned<bool> undef = true;
auto undef_ptr = builder_.ManageCopyOf(&undef);
id.type = llcpp::fuchsia::shell::ShellType::WithUndef(fidl::unowned_ptr(undef_ptr));
break;
}
case ValueType::kInt8:
id.value_id = builder_.AddIntegerLiteral(value.GetInt8());
id.type = GetBuiltin(llcpp::fuchsia::shell::BuiltinType::INT8);
break;
case ValueType::kUint8:
id.value_id = builder_.AddIntegerLiteral(value.GetUint8());
id.type = GetBuiltin(llcpp::fuchsia::shell::BuiltinType::UINT8);
break;
case ValueType::kInt16:
id.value_id = builder_.AddIntegerLiteral(value.GetInt16());
id.type = GetBuiltin(llcpp::fuchsia::shell::BuiltinType::INT16);
break;
case ValueType::kUint16:
id.value_id = builder_.AddIntegerLiteral(value.GetUint16());
id.type = GetBuiltin(llcpp::fuchsia::shell::BuiltinType::UINT16);
break;
case ValueType::kInt32:
id.value_id = builder_.AddIntegerLiteral(value.GetInt32());
id.type = GetBuiltin(llcpp::fuchsia::shell::BuiltinType::INT32);
break;
case ValueType::kUint32:
id.value_id = builder_.AddIntegerLiteral(value.GetUint32());
id.type = GetBuiltin(llcpp::fuchsia::shell::BuiltinType::UINT32);
break;
case ValueType::kInt64:
id.value_id = builder_.AddIntegerLiteral(value.GetInt64());
id.type = GetBuiltin(llcpp::fuchsia::shell::BuiltinType::INT64);
break;
case ValueType::kUint64:
id.value_id = builder_.AddIntegerLiteral(value.GetUint64());
id.type = GetBuiltin(llcpp::fuchsia::shell::BuiltinType::UINT64);
break;
// Float ?
case ValueType::kString:
id.value_id = builder_.AddStringLiteral(value.GetString()->value());
id.type = GetBuiltin(llcpp::fuchsia::shell::BuiltinType::STRING);
break;
case ValueType::kObject: {
builder_.OpenObject();
Object* object = value.GetObject();
const std::shared_ptr<ObjectSchema> schema = object->schema();
ObjectSchema* schema_ptr = schema->AsObjectSchema();
for (auto& field : schema_ptr->fields()) {
auto value = object->GetField(field.get());
auto expression_id = Set(*value);
builder_.AddField(field->name(), expression_id.value_id, std::move(expression_id.type));
}
shell::console::AstBuilder::NodePair value_type = builder_.CloseObject();
id.value_id = value_type.value_node;
auto type_ptr = builder_.ManageCopyOf(&value_type.schema_node);
id.type = llcpp::fuchsia::shell::ShellType::WithObjectSchema(fidl::unowned_ptr(type_ptr));
break;
}
}
return id;
}
llcpp::fuchsia::shell::ShellType GetBuiltin(llcpp::fuchsia::shell::BuiltinType type) {
llcpp::fuchsia::shell::BuiltinType* type_ptr = builder_.ManageCopyOf(&type);
return llcpp::fuchsia::shell::ShellType::WithBuiltinType(fidl::unowned_ptr(type_ptr));
}
private:
shell::console::AstBuilder builder_;
};
void Service::LoadGlobal(::fidl::StringView name, LoadGlobalCompleter::Sync completer) {
LoadGlobalHelper helper;
const Variable* variable = interpreter_->SearchGlobal(std::string(name.data(), name.size()));
if (variable != nullptr) {
Value value;
interpreter_->LoadGlobal(variable, &value);
// TODO: Consider having the type stored along with the value, for visibility by the client.
helper.Set(value);
}
completer.Reply(helper.nodes());
}
void Service::Shutdown(ShutdownCompleter::Sync completer) {
// Shutdown the interpreter. If we have some memory leaks, this will generate errors.
std::vector<std::string> errors;
interpreter_->Shutdown(&errors);
// Send the potential errors to the caller.
std::vector<fidl::StringView> error_view;
for (const auto& error : errors) {
error_view.emplace_back(fidl::unowned_ptr(error.c_str()), error.size());
}
completer.Reply(fidl::unowned_vec(error_view));
// Erase the service. That also closes the handle which means that if the client sends a request
// after the shutdown, it will receive a ZX_ERR_PEER_CLOSED.
server_->EraseService(this);
}
void Service::AddIntegerLiteral(ServerInterpreterContext* context, uint64_t node_file_id,
uint64_t node_node_id,
const llcpp::fuchsia::shell::IntegerLiteral& node, bool root_node) {
if (node.absolute_value.count() > 1) {
interpreter_->EmitError(context->execution_context(),
"Infinite precision integers not supported for node " +
std::to_string(node_file_id) + ":" + std::to_string(node_node_id));
return;
}
uint64_t absolute_value = 0;
if (node.absolute_value.count() > 0) {
absolute_value = node.absolute_value[0];
}
bool negative = node.negative && (absolute_value > 0);
auto result = std::make_unique<IntegerLiteral>(interpreter(), node_file_id, node_node_id,
absolute_value, negative);
interpreter_->AddExpression(context, std::move(result), root_node);
}
void Service::AddObjectSchema(ServerInterpreterContext* context, uint64_t node_file_id,
uint64_t node_node_id,
const llcpp::fuchsia::shell::ObjectSchemaDefinition& node,
bool root_node) {
std::vector<std::shared_ptr<ObjectFieldSchema>> fields;
for (auto& field : node.fields) {
fields.push_back(
interpreter_->GetObjectFieldSchema(context, NodeId(field.file_id, field.node_id)));
}
auto definition =
std::make_shared<ObjectSchema>(interpreter(), node_file_id, node_node_id, std::move(fields));
interpreter_->AddObjectSchema(context, definition, root_node);
}
void Service::AddObjectSchemaField(
ServerInterpreterContext* context, uint64_t node_file_id, uint64_t node_node_id,
const llcpp::fuchsia::shell::ObjectFieldSchemaDefinition& field_type, bool root_node) {
auto definition = std::make_shared<ObjectFieldSchema>(
interpreter(), node_file_id, node_node_id, field_type.name.data(),
GetType(context, node_file_id, node_node_id, field_type.type));
interpreter_->AddObjectFieldSchema(context, definition, root_node);
}
void Service::AddObject(ServerInterpreterContext* context, uint64_t node_file_id,
uint64_t node_node_id, const llcpp::fuchsia::shell::ObjectDefinition& node,
bool root_node) {
NodeId schema_node_id(node.object_schema.file_id, node.object_schema.node_id);
Node* schema_node = interpreter_->GetNode(schema_node_id);
if (schema_node == nullptr) {
interpreter_->EmitError(context->execution_context(), "Schema of object variable not defined");
return;
}
auto schema_object = schema_node->AsObjectSchema();
if (schema_object == nullptr) {
interpreter_->EmitError(context->execution_context(), "IR mismatch: Node type is not schema");
return;
}
std::vector<std::unique_ptr<ObjectDeclarationField>> fields;
fields.reserve(node.fields.count());
for (auto& field : node.fields) {
NodeId field_id(field.file_id, field.node_id);
std::unique_ptr<ObjectDeclarationField> field_node = context->GetObjectField(field_id);
fields.emplace_back(std::move(field_node));
}
auto definition = std::make_unique<ObjectDeclaration>(interpreter(), node_file_id, node_node_id,
schema_object, std::move(fields));
interpreter_->AddExpression(context, std::move(definition), root_node);
}
void Service::AddObjectField(ServerInterpreterContext* context, uint64_t node_file_id,
uint64_t node_node_id,
const llcpp::fuchsia::shell::ObjectFieldDefinition& node,
bool root_node) {
NodeId schema_id(node.object_field_schema.file_id, node.object_field_schema.node_id);
Node* schema_node_raw = interpreter_->GetNode(schema_id);
if (schema_node_raw == nullptr) {
interpreter_->EmitError(context->execution_context(), "Type of object field not defined");
return;
}
if (schema_node_raw->AsObjectFieldSchema() == nullptr) {
interpreter_->EmitError(context->execution_context(),
"Node id provided for object field schema is not object field schema.");
return;
}
auto schema_node = schema_node_raw->AsObjectFieldSchema();
NodeId value_id(node.value.file_id, node.value.node_id);
std::unique_ptr<Expression> value = interpreter_->GetExpression(
context, NodeId(node_file_id, node_node_id), "expression", value_id);
auto definition = std::make_unique<ObjectDeclarationField>(
interpreter(), node_file_id, node_node_id, schema_node, std::move(value));
interpreter_->AddObjectField(context, std::move(definition), root_node);
}
void Service::AddVariableDefinition(ServerInterpreterContext* context, uint64_t node_file_id,
uint64_t node_node_id,
const llcpp::fuchsia::shell::VariableDefinition& node,
bool root_node) {
std::unique_ptr<Expression> initial_value = interpreter_->GetNullableExpression(
context, NodeId(node.initial_value.file_id, node.initial_value.node_id));
std::unique_ptr<Type> type = GetType(context, node_file_id, node_node_id, node.type);
if (type->IsUndefined()) {
interpreter_->EmitError(context->execution_context(), NodeId(node_file_id, node_node_id),
"Type not defined.");
return;
}
auto result = std::make_unique<VariableDefinition>(interpreter(), node_file_id, node_node_id,
GetView(node.name), std::move(type),
node.mutable_value, std::move(initial_value));
interpreter_->AddInstruction(context, std::move(result), root_node);
}
void Service::AddStringLiteral(ServerInterpreterContext* context, uint64_t node_file_id,
uint64_t node_node_id, const ::fidl::StringView& node,
bool root_node) {
auto result = std::make_unique<StringLiteral>(interpreter(), node_file_id, node_node_id,
std::string_view(node.data(), node.size()));
interpreter_->AddExpression(context, std::move(result), root_node);
}
void Service::AddVariable(ServerInterpreterContext* context, uint64_t node_file_id,
uint64_t node_node_id, const llcpp::fuchsia::shell::NodeId& node,
bool root_node) {
auto result = std::make_unique<ExpressionVariable>(interpreter(), node_file_id, node_node_id,
NodeId(node.file_id, node.node_id));
interpreter_->AddExpression(context, std::move(result), root_node);
}
void Service::AddAddition(ServerInterpreterContext* context, uint64_t node_file_id,
uint64_t node_node_id, const llcpp::fuchsia::shell::Addition& node,
bool root_node) {
std::unique_ptr<Expression> left =
interpreter_->GetExpression(context, NodeId(node_file_id, node_node_id), "left",
NodeId(node.left.file_id, node.left.node_id));
std::unique_ptr<Expression> right =
interpreter_->GetExpression(context, NodeId(node_file_id, node_node_id), "right",
NodeId(node.right.file_id, node.right.node_id));
auto result = std::make_unique<Addition>(interpreter(), node_file_id, node_node_id,
node.with_exceptions, std::move(left), std::move(right));
interpreter_->AddExpression(context, std::move(result), root_node);
}
// - Server ----------------------------------------------------------------------------------------
Server::Server() : loop_(&kAsyncLoopConfigAttachToCurrentThread) {}
bool Server::Listen() {
zx_handle_t directory_request = zx_take_startup_handle(PA_DIRECTORY_REQUEST);
if (directory_request == ZX_HANDLE_INVALID) {
FX_LOGS(ERROR) << "error: directory_request was ZX_HANDLE_INVALID";
return false;
}
svc_dir_t* dir = nullptr;
zx_status_t status = svc_dir_create(loop_.dispatcher(), directory_request, &dir);
if (status != ZX_OK) {
FX_LOGS(ERROR) << "error: svc_dir_create failed: " << status << " ("
<< zx_status_get_string(status) << ")";
return false;
}
status = svc_dir_add_service(dir, "svc", "fuchsia.shell.Shell", this, connect);
if (status != ZX_OK) {
FX_LOGS(ERROR) << "error: svc_dir_add_service failed: " << status << " ("
<< zx_status_get_string(status) << ")" << std::endl;
return false;
}
return true;
}
zx_status_t Server::IncomingConnection(zx_handle_t service_request) {
return fidl::Bind(loop_.dispatcher(), zx::channel(service_request),
AddConnection(service_request));
}
} // namespace server
} // namespace interpreter
} // namespace shell