MV Language - modrpc/info GitHub Wiki

Table of Contents

Definitions

Property Definition

  • Ⓜ️ PROPDEF: [exported] property P0;
    • A property is a piece of data which can be read/written by devices. A property, defined without the exported attribute, is local and can be only accessed by the device which defines it. An exported property can be accessed by devices other than the one which defines it.
    • When there is a name conflict with any of existing properties, functions, events, or reactors, the given property will not be defined.
    • A persistent property stores the value across different lifetimes of the runtime which executes the MV code. In some sense, a persistent property is more like a table in a DB rather than a variable in a program. The value of a volatile property loses its value on the shutdown of the runtime. A volatile property is more like typical variable in a program. By defauilt, a property is persistent.

Event Definition

  • Ⓜ️ EVENTDEF: [exported] event E0;
    • An event is a class of information which can be pushed to devices which subscribe it. A device which defines an event, say E0 can publish an occurrence of the event. An event can be either local or exported -- only exported events can be subscribed by other devices.
  • Ⓜ️ TIMERDEF: timer T0(timeout [,period]);
    • A timer is a special type of event which is generated when the given timeout expires. When a period is given, event occurrences will be generated periodically. When the period is not specified, the timer event will not be generated any more.

Function Definition

  • Ⓜ️ FUNDEF: [exported] function F (A1 A2 ...) = { S }
    • A function is a parameterized code, which can be called with arguments. An exported function can be called by other devices.
    • There is a special function, say :INIT which is always executed when the runtime first boots. This is just like main in C programs.
    • Functions cannot be executed by itself. There must exist a "caller" -- the only exception is :INIT.

Expressions

Constants

  • Ⓜ️ NUMBER: 1 0 -1 1.1 2.3 -3.3 3E23
  • Ⓜ️ STRING: "" "this is a string"
  • Ⓜ️ TIME: #10s #10s2ms

Name References

  • Ⓜ️ NAMEREF: [[dev0]:]prop0 [[dev1]:]E0

Select Expressions

  • Ⓜ️ MAPREF: P0.key
  • Ⓜ️ VECREF: P1[10]

Function Calls

  • Ⓜ️ FUNCALL: [[device]:]foo(arg0, args)
    • A blocking function call will call the function and will suspend until the return value is available.
  • Ⓜ️ FUNCALL_ASYNC: device:foo!(arg0, args)

Statements

Assignments

  • Ⓜ️ ASSIGN: L = R

Fork-Join

  • Ⓜ️ FORKJOIN: fork { S1; S2; } join([ANY|ALL|NONE])

Blocks

  • Ⓜ️ SEQBLOCK: { S1; S2; }
    • Executes the contained statements sequentially.
  • Ⓜ️ REACTBLOCK: @([[dev1:]event] e) { S1; S2; }
    • REACTBLOCK suspends execution until an instance of event, say BatteryLowEvent is received. This event instance will be bound to a name e in block { S1; S2; } -- i.e. S1 or S2 can refer to e to access the payload of event instance which caused this reactive block to be executed.
    • If the sensitivity list contains only a event variable (e.g. e), this variable must have been declared in a module port.
    • This reactive block can be used to handle errors during distributed computation. In particular, special system-event will be introduced, say :MVREPLY, which represents a reply message which is obtained as a reply to a request.
      • If one to call a function in a nonblocking way, one can just call the function without any reactive block. Any error during the remote function call (or any remote service request) without reactive block will cause the entire function or reactor to exit.

Branching

  • Ⓜ️ IF-THEN-ELSE: if (C) S1 if (C) S1 else S2

Loops

  • Ⓜ️ WHILE: while (C) S
  • Ⓜ️ FOR: for (I; C; S1) S

Jumps

  • Ⓜ️ RETURN: return return V
  • Ⓜ️ CONTINUE: continue
  • Ⓜ️ BREAK: break

Function Calls

  • Ⓜ️ TASKCALL: [[dev]:]foo(arg0, arg1);
    • This (blocking) function call suspends the execution until the function execution is finished in the server device.
  • Ⓜ️ TASKCALL_ASYNC: dev:foo!(arg0, arg1);
    • foo must be a remote function.
    • This (nonblocking) function call will not suspend the execution, regardless of the execution/success of the function or not. The next statement will be executed, if any.

Reactors

Reactor Definitions

  • Ⓜ️ REACTDEF: reactor R0 = @([[[dev]:]EV] e){ S1; S2; }
    • Reactor definition is similar to function definition but the body of the reactor must be a reactive block. This reactor is evaluated only when an instance of EV is generated.
    • When the event is an external event, say extdev:batterylow, when the runtime is loaded, it will contact the device extdev and subscribe to its batterylow event. On any exception (e.g. device is not one, or device does not have (or no longer have) the given event, the reactor will be inactive -- until when?)
    • The sensitivity list of a reactor definition can contain either a constant or a variable event.

Modules

Module Definitions

  • Ⓜ️ MODULEDEF: module M0(P0, P1, ...) { ... }
    • Modules allow to encapulate MV artifacts (properties, events) under a namespace provided by the module.
    • Modules can be defined with a list of ports, where a port, which can be used inside the module. A port is untyped (just like properties, events, etc.), and can be a property, event, or a function.

Misc

Imported Function Declaration

  • Ⓜ️ FUNDECL: import "C" function F(T1 A1, T2 A2 ...) {S}
    • Depending on the language in which the imported function is defined, the signature may need to contain some functions.
    • FIX: We don't add this import facility as part of system library function OR a pragma. e.g. $import_function("C", "int foo(int a, char *b);");

Semantics

Failiure Semantics

  • A reactor or a function is a "unit of failure" -- i.e. when an "uncaught failure" happens, we stop the evaluation of the reactor OR the closest-enclosing function which contains the failure point.
  • Whenever we stop due to uncaught failure, we generate an special system event, say :SYSERR.
⚠️ **GitHub.com Fallback** ⚠️