Code Monkey home page Code Monkey logo

pendulum's Introduction

Readme

Description

pendulum is a language dedicated to the programming of reactive systems on the Web. It has a powerful expressivity to describe synchronous concurrent systems communicating with broadcasted signals. Its constructions and implementation are mostly based on Esterel. The language is embedded in OCaml as a syntax extension. It allows the programmer to describe reactive machines as OCaml values, and run them on signals arguments. The execution of concurrency in pendulum is completely sequential and the scheduling is static. (similar work and inspiration)

The core language is completely compatible with vanilla OCaml compiler.

We would be grateful for any feedback on this implementation, but beware that this prototype is still in active developpement

Documentation

see a slight documentation and examples

Examples and benchmark

Reactive player example

A UI for playing video with customs controls: play/pause, seek, display time

let%sync reactive_player =
  input play_pause; (* the button *)
  input progress_bar; (* the progress element *)
  input media; (* the video element *)
  input time_a; (* the a elt displaying time*)

  let no_update = () in
  let state = Js.to_bool media##.paused in

  (* when the video starts or restarts playing,
     switch the display of the button*)
  loop (
    present media##onplay
      !(play_pause##.textContent := Js.some @@ Js.string "Pause"); pause)

  (* switch state when the button is clicked *)
  || loop (present play_pause##onclick (emit state (not !!state)); pause)

  (* when the state changes, update the media and the button *)
  || loop (present state !(update_state (!!state) media play_pause); pause)

  (* when mouse is down on the progress bar, start emit `no_update` every instants
     until mouse is up to block the following task. When mouse ups,
     update the media in consequence *)
  || loop (
    await progress_bar##onmousedown;
    trap t' (loop (
        emit no_update ();
        present progress_bar##onmouseup
          (!(update_media media progress_bar); exit t');
        pause)
      ); pause)

  (* Each progression steps of the video, update the progress bar
     with the right value. Except if no_update is present. *)
  || loop (
    present media##onprogress (
      present no_update nothing !(update_slider progress_bar media)
      ||
      !(update_time_a media (!!time_a))
    ); pause)

see this example for the full code

TodoMVC benchmark

Check out example and the benchmark results

Sample of pendulum execution in Chrome, Fedora 19

  1. Add 100 items
  2. Select 100 items (one by one)
  3. Remove 100 items (one by one)

The reason why it's so fast, is that adding 100 items runs between two request animation frames. Ids of items are gathered in signals as lists and the instant function just apply the action to all elements of the list in the following requestAnimationFrame. So it takes only one logical instant which is basically the execution of a list iterator.

Install

with opam (easier)

opam 1.2 with switch 4.05.0 (minimum)

sh pin.sh
opam pin add -y pendulum-compiler git://github.com/remyzorg/pendulum.git
opam pin add -y pendulum-lib git://github.com/remyzorg/pendulum.git
opam pin add -y pendulum-ppx git://github.com/remyzorg/pendulum.git
  • an example to use pendulum as syntax extension with ocamlbuild

ocamlbuild -use-ocamlfind -pkgs pendulum-lib,pendulum-ppx \ <file-without-ext>.byte

without opam

dependencies: jbuilder, ppx_tools

  1. git clone git://github.com/remyzorg/pendulum.git
  2. cd pendulum
  3. make
  4. make install

Licensing and context

This project is under MIT public license. It started in the context of UCF project.

pendulum's People

Contributors

remyzorg avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Forkers

voila

pendulum's Issues

Handle run properly !

To share signals between host and calls, it is possible to use an object interface for program descriptions too. It is then possible to provide an instanciation methode p#create to the user and an instanciation function p#create_run that take different arguments. I one case i takes only signal initial values and in the other case it takes signals structures.

Just beware that p#create_run must ignore animate

runtime error

When I try some of the examples (TodoMVC for instance) I get the following in the Javascript console:

uncaught exception: 0,248,Assert_failure,-11,0,src/runtime/runtime_misc.ml,56,19 <unknown>

I've tried on Chrome, Safari and Firefox

Handle correctly `output` signals

Several things :

  • What is the input value for an output signal ?
    • callback function ?
    • default value ?
  • What is the consequence on the run statement ?

Integer overflow on new bitset updates gathering

Warning: integer overflow: integer 0x3ffffffffffdffff (4611686018427256831) truncated to 0xfffdffff (-131073); the generated code might be incorrect.
Warning: integer overflow: integer 0x3fffffffffffffef (4611686018427387887) truncated to 0xffffffef (-17); the generated code might be incorrect.
Warning: integer overflow: integer 0x3fffffffffffff7f (4611686018427387775) truncated to 0xffffff7f (-129); the generated code might be incorrect.
Warning: integer overflow: integer 0x3ffffffffffffbff (4611686018427386879) truncated to 0xfffffbff (-1025); the generated code might be incorrect.
Warning: integer overflow: integer 0x3fffffffffffdfff (4611686018427379711) truncated to 0xffffdfff (-8193); the generated code might be incorrect.
Warning: integer overflow: integer 0x3fffffffffffbfff (4611686018427371519) truncated to 0xffffbfff (-16385); the generated code might be incorrect.
Warning: integer overflow: integer 0x3fffffffffff7fff (4611686018427355135) truncated to 0xffff7fff (-32769); the generated code might be incorrect.
Warning: integer overflow: integer 0x3ffffffffffeffff (4611686018427322367) truncated to 0xfffeffff (-65537); the generated code might be incorrect.
Warning: integer overflow: integer 0x3fffffffff7fffff (4611686018418999295) truncated to 0xff7fffff (-8388609); the generated code might be incorrect.
Warning: integer overflow: integer 0x3fffffffffbfffff (4611686018423193599) truncated to 0xffbfffff (-4194305); the generated code might be incorrect.
Warning: integer overflow: integer 0xb800000000 (790273982464) truncated to 0x0 (0); the generated code might be incorrect.
Warning: integer overflow: integer 0x3ffffffffbffffff (4611686018360279039) truncated to 0xfbffffff (-67108865); the generated code might be incorrect.
Warning: integer overflow: integer 0x500000000 (21474836480) truncated to 0x0 (0); the generated code might be incorrect.
Warning: integer overflow: integer 0x80000000 (2147483648) truncated to 0x80000000 (-2147483648); the generated code might be incorrect.
Warning: integer overflow: integer 0x4000000000 (274877906944) truncated to 0x0 (0); the generated code might be incorrect.
Warning: integer overflow: integer 0x3fffffdfffffffff (4611685880988434431) truncated to 0xffffffff (-1); the generated code might be incorrect.
Warning: integer overflow: integer 0x1000000000000 (281474976710656) truncated to 0x0 (0); the generated code might be incorrect.

Possibily generated by PPX

If the same event occurs several time between two instants, only the last one is visible

  • improve the language with gathered signals to fix this
  • tried just by changing the type of events in ocaml to lists but then it's not
    possible anymore to get environnement values at anytime
  • add a syntax :
input items (fun items x -> x :: items);

and

input (newit : inputElement Js.t)
  (onkeydown (
      fun omm ev ->
        if newit##.value##.length > 0 && ev##.keyCode = 13 then
          newit##.value :: omm else omm) [])
;

or even

let%sync prog ?(items=fun items x -> x :: items) = ... 

Typing problem when generating gathered event-mapped signals

The scope of the type variables is weird, see this example :

let make v1 v2 = v1, v2 in
let a =
  let (x, y) : ('a * ('a -> 'b -> 'a)) =
    ("", fun acc x -> acc ^ x)
  in make x y
in
let b =
  let (x, y) : ('a * ('a -> 'b -> 'a)) =
    ([], fun acc x -> x :: acc)
  in make x y 
in a, b

see eb9da6d

Some remarks to improve documentation

  • Language documentation
    • Call Documentation "Syntax"
    • Information about the single syntax elements especially the statements.
    • General informations like how the JS events and Pendulum signals interact.
  • Web based Esterel engine : an input/output area like reacting on simple mouse clicks
    with a simple source text field.
  • Comments : More educational comments in the code of the examples.

(Thx Ben for those remarks)

Several features are missing

  • add first class machines (necessary)
  • maintain signals values or presence informations between steps
  • gathering operators at signal definitions (several emission of the same signal at the same instant
  • pre
  • n-ary parallel operator and/or gathering (at signals definition)

Add a `run` statement

The problem of the run statement meets the one of locals and can be handle in the same way in GRC :

  • put the Run induction case in grc and in depth / surface do
    • if i'm not selected,
      • I Initialize the machine with the corrects inputs then I run one step
    • If I am,
      • I set present with the correct value every inputs that are actually present
      • I run one step
  • About the code generation
    • All runs must define a global value outside of step (as local signals)
    • each run has a specific id

Improper use of local signal expression value during initialization

Problem : If there is any side effect in local signal definition expression, it will be executed when the synchronous program is instantiated, which is incorrect.

Solution : use Obj.magic 0 as value for local signals initialization instead of their actual expression.

Invalid argument index out of bound

From this code :

let%sync reactive_player =
  input play;
  input start_slide;
  input stop_slide;

  let cant_update = () in
  loop begin
    present play (atom (print_string "play"));
    pause
  end
  || loop begin
    await start_slide;
    trap t' (
      loop (
        present stop_slide nothing (exit t')
      ); pause
    );
    pause
  end

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.