| // 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. | |
| enum ExecuteResult : 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. | |
| struct NodeId { | |
| /// The id of the file. | |
| uint64 file_id; | |
| /// The id of the node for that file. | |
| uint64 node_id; | |
| }; | |
| /// Defines a Location for an error. | |
| table Location { | |
| /// Defined for error relative to an AST node. For native methods, this is not defined. | |
| 1: NodeId node_id; | |
| }; | |
| /// Defines the builtin types. | |
| enum BuiltinType : 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. | |
| struct ObjectFieldSchemaDefinition { | |
| /// The type of the field. | |
| ShellType type; | |
| /// The name of the field. | |
| string:MAX name; | |
| }; | |
| struct ObjectSchemaDefinition { | |
| vector<NodeId>:MAX fields; | |
| }; | |
| /// Defines a type used by the shell. | |
| union ShellType { | |
| /// Undefined type (can be used when the type can be inferred). | |
| 1: bool undef; | |
| /// A builtin type. | |
| 2: BuiltinType builtin_type; | |
| /// The NodeId corresponding to an object schema. | |
| 3: NodeId object_schema; | |
| }; | |
| /// Defines an integer value. | |
| struct IntegerLiteral { | |
| /// The absolute value of the value. The first value in the vector is the less significant 64 | |
| /// bits. | |
| vector<uint64>:MAX absolute_value; | |
| /// If true, the value is negative (-absolute_value). | |
| /// There is no negative zero. That means that, for zero, negative should be false. | |
| bool negative; | |
| }; | |
| struct ObjectFieldDefinition { | |
| /// The schema of this field. | |
| NodeId object_field_schema; | |
| /// The nodeid containing the value of this field. | |
| NodeId value; | |
| }; | |
| /// Defines an object value. | |
| struct ObjectDefinition { | |
| /// A list of nodes of type ObjectFieldDefinition corresponding to the fields of this object. | |
| vector<NodeId>:MAX fields; | |
| // A node of type ObjectSchemaDefinition corresponding to the type of this object. | |
| NodeId object_schema; | |
| }; | |
| /// Defines a variable. | |
| struct VariableDefinition { | |
| /// The name of the variable. | |
| string:MAX name; | |
| /// The type of the variable. | |
| ShellType type; | |
| /// True if the variable can be modified afterward. | |
| bool mutable_value; | |
| /// The node which defines the initial value. | |
| NodeId initial_value; | |
| }; | |
| /// Defines an assignment. | |
| struct Assignment { | |
| /// The destination. It must be a L Value. | |
| NodeId destination; | |
| /// The source. It's an expression. | |
| NodeId source; | |
| }; | |
| /// Defines an addition. | |
| struct Addition { | |
| /// Throws an exception if we have an overflow or an underflow. | |
| bool with_exceptions; | |
| /// Left term. | |
| NodeId left; | |
| /// Right term. | |
| NodeId right; | |
| }; | |
| /// Defines a node (expression, instruction, ...). | |
| union Node { | |
| /// An integer value. | |
| 1: IntegerLiteral integer_literal; | |
| /// A variable. | |
| 2: VariableDefinition variable_definition; | |
| // A schema definition. | |
| 3: ObjectSchemaDefinition object_schema; | |
| // A field schema definition | |
| 4: ObjectFieldSchemaDefinition field_schema; | |
| // An object definition. | |
| 5: ObjectDefinition object; | |
| // A object field definition | |
| 6: ObjectFieldDefinition object_field; | |
| /// A string value. | |
| 7: string:MAX string_literal; | |
| /// The value of a previously defined variable. It refers to a previously created variable | |
| /// definition using its name. | |
| 8: string:MAX variable; | |
| /// Emits a result. The value of the expression is sent back to the client using OnResult. | |
| 9: NodeId emit_result; | |
| /// 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. | |
| struct NodeDefinition { | |
| /// Id of the node. | |
| NodeId node_id; | |
| /// 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. | |
| bool root_node; | |
| }; | |
| /// 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(uint64 context_id); | |
| /// 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(uint64 context_id, vector<NodeDefinition>:MAX nodes); | |
| /// 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(uint64 context_id); | |
| /// 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(uint64 context_id); | |
| /// 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() -> (vector<string:MAX>:MAX errors); | |
| /// 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(uint64 context_id, vector<Location>:MAX locations, string:MAX error_message); | |
| /// Signals that the shell has dumped all the pending instructions. | |
| /// | |
| /// - `context_id` the execution context id. | |
| -> OnDumpDone(uint64 context_id); | |
| /// 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(uint64 context_id, ExecuteResult result); | |
| /// 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(uint64 context_id, string:MAX result, bool partial_result); | |
| /// 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(uint64 context_id, vector<Node>:MAX nodes, bool partial_result); | |
| }; |