Skip to content

do expression, generator function and for loop #37

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
xialvjun opened this issue Dec 11, 2018 · 6 comments
Closed

do expression, generator function and for loop #37

xialvjun opened this issue Dec 11, 2018 · 6 comments

Comments

@xialvjun
Copy link

xialvjun commented Dec 11, 2018

import React from "react";
import { render } from "react-dom";
import { Element, init_state, init_value, init_ref, genc } from "@xialvjun/react-element";

export const GeneratorComponent = genc(function*(props) {
  const [pagination] = yield <Element construct={init_state({ limit: 10, offset: 0 })} />;
  const main = (
    <div>
      <Pager limit_and_offset={pagination.state} onChange={limit_and_offset => pagination.set_state(limit_and_offset)} />
      {do {
        const [editing_item] = yield <Element construct={init_value(null)} />;
        <>
          {do {
            const [{ loading, error, data }] = yield <Query query={all_items} variables={pagination.state} />;
            <table>
              <thead>
                <tr>
                  <th>name</th>
                  <th>age</th>
                  <th>photo</th>
                  <th>operation</th>
                </tr>
              </thead>
              <tbody>
                {loading && (
                  <tr>
                    <td colSpan={999}>loading</td>
                  </tr>
                )}
                {error && (
                  <tr>
                    <td colSpan={999}>{`${error}`}</td>
                  </tr>
                )}
                {(data.all_items || []).map(it => (
                  <tr key={it.id}>
                    <td>{it.name}</td>
                    <td>{it.age}</td>
                    <td>
                      <img src={it.photo} />
                    </td>
                    <td>
                      <button onClick={_ => editing_item.set_value(it)}>edit</button>
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          }}
          {editing_item.value && (
            <Modal open>
              <form>
                <div>
                  <label>name</label>
                  <input type="text" value={e => editing_item.set_partial("name", e.target.value)} />
                </div>
                <div>
                  <label>age</label>
                  <input type="number" value={e => editing_item.set_partial("age", parseInt(e.target.value) || 18)} />
                </div>
                <div>
                  <label>photo</label>
                  {do {
                    const [{ ref }] = yield <Element construct={init_ref()} />;
                    <Modal ref={ref} trigger={editing_item.value.photo ? <img src={editing_item.value.photo} /> : <Icon name="avatar" />}>
                      <ImageSelector
                        on_select={img => {
                          editing_item.set_partial("photo", img.url);
                          ref.close_modal();
                        }}
                      />
                    </Modal>
                  }}
                </div>
                {do {
                  const [edit_item_api, edit_item_res] = yield <Mutation mutation={edit_item} />;
                  <button type="button" disabled={edit_item_res.loading} onClick={_ => edit_item_api({ variables: editing_item.value })}>
                    submit
                  </button>
                }}
              </form>
            </Modal>
          )}
          <h4>and for loop</h4>
          {do {
            let c = 0;
            for (let i = 0; i < 5; i++) {
              // if genc find what yield is not a react element, it will not modify the yield thing.
              c += yield i;
            }
            let a = yield 1;
            let b = yield 2;
            <div>
              <p>a + b = {a + b}</p>
              <p>the result of c is {c}</p>
            </div>
          }}
        </>
      }}
    </div>
  );

  const rest_to_show_do_isnot_totally_hoist = (
    <div>
      {do {
        let c = 0;
        for (let i = 0; i < 5; i++) {
          // if genc find what yield is not a react element, it will not modify the yield thing.
          c += yield i;
        }
        let a = yield 1;
        let b = yield 2;
        <div>
          <p>a + b = {a + b}</p>
          <p>the result of c is {c}</p>
        </div>
      }}
    </div>
  );

  return (
    <div>
      {main}
      {rest_to_show_do_isnot_totally_hoist}
    </div>
  );
});

render(<GeneratorComponent />, document.querySelector("#root"));

But it compiles wrong...

@xialvjun
Copy link
Author

xialvjun commented Dec 12, 2018

In above codes, there are many dos.

They should compile to:

import React from "react";
import { render } from "react-dom";
import { Element, init_state, init_value, init_ref, genc } from "@xialvjun/react-element";

export const GeneratorComponent = genc(function*(props) {
  const [pagination] = yield <Element construct={init_state({ limit: 10, offset: 0 })} />;
  let do_1;
  {
    const [editing_item] = yield <Element construct={init_value(null)} />;
    let do_2;
    {
      const [{ loading, error, data }] = yield <Query query={all_items} variables={pagination.state} />;
      do_2 = (
        <table>
          <thead>
            <tr>
              <th>name</th>
              <th>age</th>
              <th>photo</th>
              <th>operation</th>
            </tr>
          </thead>
          <tbody>
            {loading && (
              <tr>
                <td colSpan={999}>loading</td>
              </tr>
            )}
            {error && (
              <tr>
                <td colSpan={999}>{`${error}`}</td>
              </tr>
            )}
            {(data.all_items || []).map(it => (
              <tr key={it.id}>
                <td>{it.name}</td>
                <td>{it.age}</td>
                <td>
                  <img src={it.photo} />
                </td>
                <td>
                  <button onClick={_ => editing_item.set_value(it)}>edit</button>
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      );
    }
    let do_3;
    {
      const [{ ref }] = yield <Element construct={init_ref()} />;
      do_3 = (
        <Modal ref={ref} trigger={editing_item.value.photo ? <img src={editing_item.value.photo} /> : <Icon name="avatar" />}>
          <ImageSelector
            on_select={img => {
              editing_item.set_partial("photo", img.url);
              ref.close_modal();
            }}
          />
        </Modal>
      );
    }
    let do_4;
    {
      const [edit_item_api, edit_item_res] = yield <Mutation mutation={edit_item} />;
      do_4 = (
        <button type="button" disabled={edit_item_res.loading} onClick={_ => edit_item_api({ variables: editing_item.value })}>
          submit
        </button>
      );
    }
    let do_5;
    {
      let c = 0;
      for (let i = 0; i < 5; i++) {
        // if genc find what yield is not a react element, it will not modify the yield thing.
        c += yield i;
      }
      let a = yield 1;
      let b = yield 2;
      do_5 = (
        <div>
          <p>a + b = {a + b}</p>
          <p>the result of c is {c}</p>
        </div>
      );
    }
    do_1 = (
      <>
        {do_2}
        {editing_item.value && (
          <Modal open>
            <form>
              <div>
                <label>name</label>
                <input type="text" value={e => editing_item.set_partial("name", e.target.value)} />
              </div>
              <div>
                <label>age</label>
                <input type="number" value={e => editing_item.set_partial("age", parseInt(e.target.value) || 18)} />
              </div>
              <div>
                <label>photo</label>
                {do_3}
              </div>
              {do_4}
            </form>
          </Modal>
        )}
        <h4>and for loop</h4>
        {do_5}
      </>
    );
  }
  const main = (
    <div>
      <Pager limit_and_offset={pagination.state} onChange={limit_and_offset => pagination.set_state(limit_and_offset)} />
      {do_1}
    </div>
  );

  let do_6;
  {
    let c = 0;
    for (let i = 0; i < 5; i++) {
      // if genc find what yield is not a react element, it will not modify the yield thing.
      c += yield i;
    }
    let a = yield 1;
    let b = yield 2;
    do_6 = (
      <div>
        <p>a + b = {a + b}</p>
        <p>the result of c is {c}</p>
      </div>
    );
  }
  const rest_to_show_do_isnot_totally_hoist = <div>{do_6}</div>;

  return (
    <div>
      {main}
      {rest_to_show_do_isnot_totally_hoist}
    </div>
  );
});

render(<GeneratorComponent />, document.querySelector("#root"));

@bakkot
Copy link
Collaborator

bakkot commented Jan 30, 2021

I'm really unclear on what this is asking or asking for. Since this is several years old, I'm going to close it, but feel free to reopen if you have a concrete suggestion or question.

@bakkot bakkot closed this as completed Jan 30, 2021
@xialvjun
Copy link
Author

xialvjun commented Feb 1, 2021

function A() {
  let p = 'asdasd';
  return (
    <div>
      <p>{p}</p>
      {do {
        let b = 123;
        <button>{b}</button>
      }}
    </div>
  );
}

function B() {
  let p = 'asdasd';
  return m(
    'div',
    m('p', p),
    do {
      let b = 123;
      m('button', b)
    },
  );
}

function* C() {
  let p = yield 'asdasd';
  return m(
    'div',
    m('p', p),
    do {
      let b = yield 123;
      m('button', b)
    },
  );
}

In this code, A B is ok, but C is wrong. C compiles to:

function* C() {
  let p = yield 'asdasd';
  return m('div', m('p', p), function () {
    let b = yield 123;
    return m('button', b);
  }());
}

but I expect it to be:

function* C() {
  let p = yield 'asdasd';
  return m('div', m('p', p), yield* function* () {
    let b = yield 123;
    return m('button', b);
  }());
}

@bakkot
Copy link
Collaborator

bakkot commented Feb 1, 2021

C compiles to:

Not according to the spec. That sounds like a bug in whatever you're using to do compilation (babel?), rather than in this proposal.

@xialvjun
Copy link
Author

xialvjun commented Feb 1, 2021

So, in this spec, C do compiles to what I want it to be, it's just babel's bug ?

babel implements do expression wrong ?

@bakkot
Copy link
Collaborator

bakkot commented Feb 1, 2021

It sounds like it, yes. I see you've already opened an issue there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants