blob: 6a27fd1c8228c518e9edc5165c2d49ee8f042f56 [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.
library fuchsia.shell;
/// Result of a ExecutePendingInstructions.
type ExecuteResult = strict enum : uint32 {
/// Only used for fields. This will never be used by ExecutePedningInstructions.
UNDEF = 0;
/// Execution finished without error.
OK = 1;
/// Execution finished with errors during the execution.
EXECUTION_ERROR = 2;
/// Execution finished with errors during the semantic/analysis passes.
ANALYSIS_ERROR = 3;
};
/// Defines a unique identifier for an AST node.
type NodeId = struct {
/// The id of the file.
file_id uint64;
/// The id of the node for that file.
node_id uint64;
};
/// Defines a Location for an error.
type Location = table {
/// Defined for error relative to an AST node. For native methods, this is not defined.
1: node_id NodeId;
};
/// Defines the builtin types.
type BuiltinType = strict enum : uint32 {
/// A Boolean (true/false).
BOOL = 0;
/// An unicode character.
CHAR = 1;
/// A UTF8 string.
STRING = 2;
/// 8 bit signed integer.
INT8 = 3;
/// 8 bit unsigned integer.
UINT8 = 4;
/// 16 bit signed integer.
INT16 = 5;
/// 16 bit unsigned integer.
UINT16 = 6;
/// 32 bit signed integer.
INT32 = 7;
/// 32 bit unsigned integer.
UINT32 = 8;
/// 64 bit signed integer.
INT64 = 9;
/// 64 bit unsigned integer.
UINT64 = 10;
/// Infinite precision integer (signed).
INTEGER = 11;
/// 32 bit floating-point.
FLOAT32 = 12;
/// 64 bit floating-point.
FLOAT64 = 13;
};
/// A definition of a field of an object.
type ObjectFieldSchemaDefinition = struct {
/// The type of the field.
type ShellType;
/// The name of the field.
name string:MAX;
};
type ObjectSchemaDefinition = struct {
fields vector<NodeId>:MAX;
};
/// Defines a type used by the shell.
type ShellType = strict union {
/// Undefined type (can be used when the type can be inferred).
1: undef bool;
/// A builtin type.
2: builtin_type BuiltinType;
/// The NodeId corresponding to an object schema.
3: object_schema NodeId;
};
/// Defines an integer value.
type IntegerLiteral = struct {
/// The absolute value of the value. The first value in the vector is the less significant 64
/// bits.
absolute_value vector<uint64>:MAX;
/// If true, the value is negative (-absolute_value).
/// There is no negative zero. That means that, for zero, negative should be false.
negative bool;
};
type ObjectFieldDefinition = struct {
/// The schema of this field.
object_field_schema NodeId;
/// The nodeid containing the value of this field.
value NodeId;
};
/// Defines an object value.
type ObjectDefinition = struct {
/// A list of nodes of type ObjectFieldDefinition corresponding to the fields of this object.
fields vector<NodeId>:MAX;
// A node of type ObjectSchemaDefinition corresponding to the type of this object.
object_schema NodeId;
};
/// Defines a variable.
type VariableDefinition = struct {
/// The name of the variable.
name string:MAX;
/// The type of the variable.
type ShellType;
/// True if the variable can be modified afterward.
mutable_value bool;
/// The node which defines the initial value.
initial_value NodeId;
};
/// Defines an assignment.
type Assignment = struct {
/// The destination. It must be a L Value.
destination NodeId;
/// The source. It's an expression.
source NodeId;
};
/// Defines an addition.
type Addition = struct {
/// Throws an exception if we have an overflow or an underflow.
with_exceptions bool;
/// Left term.
left NodeId;
/// Right term.
right NodeId;
};
/// Defines a node (expression, instruction, ...).
type Node = strict union {
/// An integer value.
1: integer_literal IntegerLiteral;
/// A variable.
2: variable_definition VariableDefinition;
// A schema definition.
3: object_schema ObjectSchemaDefinition;
// A field schema definition
4: field_schema ObjectFieldSchemaDefinition;
// An object definition.
5: object ObjectDefinition;
// A object field definition
6: object_field ObjectFieldDefinition;
/// A string value.
7: string_literal string:MAX;
/// The value of a previously defined variable. It refers to a previously created variable
/// definition using its name.
8: variable string:MAX;
/// Emits a result. The value of the expression is sent back to the client using OnResult.
9: emit_result NodeId;
/// Assign an expression (L Value) with the computed value of another expression.
10: assignment Assignment;
/// An addition.
11: addition Addition;
};
/// Defines a node which has to be inserted in the AST. The node will stay pending until it is used
/// by another node.
type NodeDefinition = struct {
/// Id of the node.
node_id NodeId;
/// The node to be defined.
node Node;
/// If true, instruction nodes are added to the context's pending instructions and other nodes
/// are added to the interpreter AST.
///
/// For instructions, root_node true means that instructions have to be executed immediately
/// (in fact when ExecuteExecutionContext will be called).
///
/// For other nodes (namespaces, classes, functions, globals) root_node true means that the
/// node is directly attached to the AST root node. Root nodes stay alive across multiple
/// executions. They are available each time ExecuteExecutionContext is called even if they
/// have been defined before another call of ExecuteExecutionContext.
///
/// When root_node is false, the node is pending and must be used by another node before
/// ExecuteExecutionContext is called.
root_node bool;
};
/// Defines the protocol to communicate with a shell interpreter.
@discoverable
protocol Shell {
/// Creates an execution context. An execution context can be a very small chunk of code.
/// For example, with a command line interface for which the user types an instruction and
/// then hits enter, each instruction will be in it's own execution context. However, they all
/// share the same isolate which stores globals. Each global variable definition in an
/// execution context is created at the isolate level (and, therefore, accessible from other
/// execution context).
///
/// - `context_id` the id for the context. This id is provided by the client which must ensure
/// that the id is unique. A context_id can be reused as soon as OnExecutionDone is
/// received.
CreateExecutionContext(struct {
context_id uint64;
});
/// Adds nodes to the AST. This message can be used several time to build an AST.
///
/// - `context_id` the id for the execution context. Instructions without a container are
/// added to the context's pending instructions. All other nodes without a container are
/// added to the interpreter AST.
/// - `nodes` all the node to be inserted. Children must be inserted before their container.
/// That means that you should do a depth first traversal of your graph to generate these
/// calls.
AddNodes(struct {
context_id uint64;
nodes vector<NodeDefinition>:MAX;
});
/// Dumps all the pending instructions. This generates an OnTextResult event for each pending
/// instruction with a brief description of that instruction.
/// When everything is dumped, OnDumpDone is called. Only the instructions successfully added
/// are dumped.
///
/// - `context_id` the id for the execution context previously created with
/// CreateExecutionContext.
DumpExecutionContext(struct {
context_id uint64;
});
/// Executes all the pending instructions. This can generate one or several errors using
/// OnError.
/// When the execution is finished (all the pending instructions have been handled),
/// OnExecutionDone is called.
/// This will execute all the instructions added to the execution context is received.
/// It is illegal to add more instructions once this function has been called.
/// If you need to execute more instructions, you need to create another execution context.
///
/// - `context_id` the id for the execution context previously created with
/// CreateExecutionContext.
ExecuteExecutionContext(struct {
context_id uint64;
});
/// Delete the current interpreter. The server will close the other side of the channel.
///
/// - `errors` all the errors found by the interpreter during the shutdown (it should be
/// empty).
Shutdown() -> (struct {
errors vector<string:MAX>:MAX;
});
/// Called each time the shell detects an error. This method can be called several times.
/// The execution is done (started with ExecuteExecutionContext) when OnExecutionDone is
/// received by the client.
///
/// - `context_id` when the error is generated by an execution context, the id of the context.
/// Zero otherwise.
/// - `locations`
/// For runtime errors, this is the stack frame (inner location first).
/// For semantic errors, this is the location of the error (only one item).
/// For global errors (not relative to a file), this is empty.
/// - `error_message` the text message for the error.
-> OnError(struct {
context_id uint64;
locations vector<Location>:MAX;
error_message string:MAX;
});
/// Signals that the shell has dumped all the pending instructions.
///
/// - `context_id` the execution context id.
-> OnDumpDone(struct {
context_id uint64;
});
/// Signals that the shell has handled all the pending instructions.
/// This will be called exactly once when the ExecutionContext is completely finished (the
/// execution starts when ExecuteExecutionContext is received).
/// Once this event is called, the execution context is destroyed.
///
/// - `context_id` the execution context id.
/// - `result` the result of the execution.
-> OnExecutionDone(struct {
context_id uint64;
result ExecuteResult;
});
/// Called when an execution context has a textual result. If the result is too big to fit
/// into one message, this event is called several times.
/// This method is temporary. We will define something more powerful later (streams like stdio,
/// typed results, ...).
/// This method can be called several times.
/// The execution is done (started with ExecuteExecutionContext) when OnExecutionDone is
/// received by the client.
///
/// - `context_id` the execution context id.
/// - `result` the text of the result.
/// - `partial_result` if true, the result is partial and at least one other event will be
/// called. All the results must be concatenated to reconstruct the original text.
-> OnTextResult(struct {
context_id uint64;
result string:MAX;
partial_result bool;
});
/// Called when an execution context has a result (emit_result instruction). If the result is
/// too big to fit into one message, this event is called several times.
/// This event can be called several times for one context if several emit_result instructions
/// are used.
///
/// - `context_id` the execution context id.
/// - `nodes` the nodes of the result. The last node of OnResult for which partial_result is
/// false is the root node which defines the result (all the other nodes are children of
/// this node). All nodes are implicitly numbered starting at one for the first node in the
/// vector.
/// - `partial_result` if true, the result is partial and at least one other event will be
/// called. All the nodes must be used to reconstruct the original value.
-> OnResult(struct {
context_id uint64;
nodes vector<Node>:MAX;
partial_result bool;
});
};