calculator.capnp (4651B)
1 # Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors 2 # Licensed under the MIT License: 3 # 4 # Permission is hereby granted, free of charge, to any person obtaining a copy 5 # of this software and associated documentation files (the "Software"), to deal 6 # in the Software without restriction, including without limitation the rights 7 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 # copies of the Software, and to permit persons to whom the Software is 9 # furnished to do so, subject to the following conditions: 10 # 11 # The above copyright notice and this permission notice shall be included in 12 # all copies or substantial portions of the Software. 13 # 14 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 # THE SOFTWARE. 21 22 @0x85150b117366d14b; 23 24 interface Calculator { 25 # A "simple" mathematical calculator, callable via RPC. 26 # 27 # But, to show off Cap'n Proto, we add some twists: 28 # 29 # - You can use the result from one call as the input to the next 30 # without a network round trip. To accomplish this, evaluate() 31 # returns a `Value` object wrapping the actual numeric value. 32 # This object may be used in a subsequent expression. With 33 # promise pipelining, the Value can actually be used before 34 # the evaluate() call that creates it returns! 35 # 36 # - You can define new functions, and then call them. This again 37 # shows off pipelining, but it also gives the client the 38 # opportunity to define a function on the client side and have 39 # the server call back to it. 40 # 41 # - The basic arithmetic operators are exposed as Functions, and 42 # you have to call getOperator() to obtain them from the server. 43 # This again demonstrates pipelining -- using getOperator() to 44 # get each operator and then using them in evaluate() still 45 # only takes one network round trip. 46 47 evaluate @0 (expression :Expression) -> (value :Value); 48 # Evaluate the given expression and return the result. The 49 # result is returned wrapped in a Value interface so that you 50 # may pass it back to the server in a pipelined request. To 51 # actually get the numeric value, you must call read() on the 52 # Value -- but again, this can be pipelined so that it incurs 53 # no additional latency. 54 55 struct Expression { 56 # A numeric expression. 57 58 union { 59 literal @0 :Float64; 60 # A literal numeric value. 61 62 previousResult @1 :Value; 63 # A value that was (or, will be) returned by a previous 64 # evaluate(). 65 66 parameter @2 :UInt32; 67 # A parameter to the function (only valid in function bodies; 68 # see defFunction). 69 70 call :group { 71 # Call a function on a list of parameters. 72 function @3 :Function; 73 params @4 :List(Expression); 74 } 75 } 76 } 77 78 interface Value { 79 # Wraps a numeric value in an RPC object. This allows the value 80 # to be used in subsequent evaluate() requests without the client 81 # waiting for the evaluate() that returns the Value to finish. 82 83 read @0 () -> (value :Float64); 84 # Read back the raw numeric value. 85 } 86 87 defFunction @1 (paramCount :Int32, body :Expression) 88 -> (func :Function); 89 # Define a function that takes `paramCount` parameters and returns the 90 # evaluation of `body` after substituting these parameters. 91 92 interface Function { 93 # An algebraic function. Can be called directly, or can be used inside 94 # an Expression. 95 # 96 # A client can create a Function that runs on the server side using 97 # `defFunction()` or `getOperator()`. Alternatively, a client can 98 # implement a Function on the client side and the server will call back 99 # to it. However, a function defined on the client side will require a 100 # network round trip whenever the server needs to call it, whereas 101 # functions defined on the server and then passed back to it are called 102 # locally. 103 104 call @0 (params :List(Float64)) -> (value :Float64); 105 # Call the function on the given parameters. 106 } 107 108 getOperator @2 (op :Operator) -> (func :Function); 109 # Get a Function representing an arithmetic operator, which can then be 110 # used in Expressions. 111 112 enum Operator { 113 add @0; 114 subtract @1; 115 multiply @2; 116 divide @3; 117 } 118 }