Langage › TypeScript et Python

Langage

Cette page n’est pas encore traduite : voici la version anglaise.

Handlers in TypeScript or Python

A project says the language its behaviour is written in: project { handlers typescript } (what archec new writes), python, or arche (the action language, translated). TypeScript bodies get self and, when a message triggered them, msg ({ name, …fields }); the API is Arche's (await wait(ms(10)), send(self.out, MSG({ f: 1 })), await goto("Run")). archec reads TypeScript without TypeScript installed, runs it in archec sim, writes arche.d.ts for the editor (archec stubs), and tells Arche the language (simulation.yaml). The contract with Arche: handlers.md; an example: examples/ts-handlers.

TypeScript that keeps to what the action language says (assignments, if, while, counted for, send, goto, wait, log, Math, the part's functions, msg.field) is portable: archec gen --target c|embassy|go translates it as it translates ```arche, and archec difftest compares it with its C. Outside that, archec check names the construct (ts-portable) and the generated code has a TODO (handlers.md).

To move a model from one language to another, archec convert-handlers main.arche --to typescript (or python, arche) rewrites its blocks, code files and guards in place: exact from ```arche, statement by statement from Python and TypeScript, what does not translate kept as a TODO(convert) comment that archec check keeps reporting.

Code in .py and .ts files#

Python bodies kept in .py files beside the model, and the way back from the Arche app and the simulator. (A body that the action language can say reads better as a ```arche block: see concepts.)

Longer code reads better in a .ts or .py file, with your editor's tooling (a .ts file binds the same way, its functions export function main(self: Ctrl) { … }):

component ctrl {
  code "ctrl.py"
  fn main                                  // ← def main(self) in ctrl.py
  in sense: i2c receives SAMPLE { on-receive on_sense }
  states { state Off; state On { on-enter enter_on } }   // on-exit: def on_exit_On, by its name
}

A fn with no block takes the def of the same name; every code property (on-enter, on-exit, on-receive, on-write, body, a transition's / action) takes the def it names; on_enter_<State>, on_exit_<State>, on_receive_<port> and on_write_<MEMORY> bind with nothing written. code on the project or a system shares a file: its defs bind only when named. A def's parameters are self and the fn's arguments, or the names Arche gives that hook (msg, rise, from_, writer…); a docstring becomes the description.

Arche keeps Python inside its project files, so archec copies each body in: the Arche project is the one the same code written inline gives (archec fmt --extract-code --write moves existing blocks out — one file per component, or --extract-code=behaviour.py for one file — and is tested to change nothing). Imports, constants and helper functions at the top of the file are copied into the bodies that use them; a copy per body, so a top-level name cannot keep state between calls — a function that changes one is an error; keep state on the component (var n, self.n). from arche import * is for the editor only: archec stubs (or the extension, on its own) writes arche.py with Arche's helpers and the model's messages and constants, so Pylance or pyright complete and check the code.

The way back: code edited in Arche, and simulator errors#

Every build writes .archec/sourcemap.json into the project: where each piece of code comes from, and the text it had.

  • Code edited in the Arche app goes back to its source. archec pull main.arche --write compares what the last build wrote, what the Arche project holds now, and what your sources give now: code changed only in Arche is written into the def of the .py file (or the ``` block of the .arche file) it came from — def becomes async def if the new body awaits. Changed on both sides is a conflict, left for you; so is a change to the top-level code copied into a body (edit that in the .py file). A build refuses to overwrite code edited in Arche and not pulled (--force drops it). In VS Code, saving in Arche offers the pull (arche.pullOnChange: ask, always, never), applied as one undoable edit; Arche: Pull Code Changes does it by hand. Only code comes back: positions, names and other edits made in the app are still overwritten by the next build.
  • Simulator errors point at your lines. Arche says ZeroDivisionError (Controller › Control loop, line 4) — line 4 of the copy. archec test and archec run build, run arche-cli and add the source line: (Controller › Control loop, line 4 → ctrl.py:32); archec where main.arche "<error>" (or arche-cli test out | archec where main.arche -) does it for any text. In VS Code, Arche: Run Tests puts each error on its line in the Problems view, and Arche: Go to Simulator Error… takes an error pasted from the Arche app. A state's on-enter and on-exit share a label in Arche's messages: both lines are offered.