「html5」という開発言語

現代ビジネスさんが大スクープ!!*1
http://gendai.ismedia.jp/articles/-/31794?page=4




アンドロイドは「html5」という開発言語を用いるインターネットベースのOS

  イ`ヘ 
 /: :| ヽ 
/ : :/  ヽ ___   _,,,:. .-: :´彡フ 
_ノ\_∠: : : : : : : : :`: :-: :,:_:/彡 / 
      ( : : : : : : : : : : : : : : `ゝ  / 
  マ  r::/: /: : | : : : : : : : : ::\ / 
      //: /: : : |: : | |: : |: _: : : :ヽ 
  ジ  {/ 7|`\/i: /|:|/|´: : : : :|ヽ 
     〉 ,‐-‐、`|7 || |_::|,_|: : :|:::|: | 
  で / r:oヽ`    /.:oヽヽ: :|: | :| 
     { {o:::::::}     {:::::0 }/: :|N 
  っ  | ヾ:::ソ     ヾ:::ソ /|: : | 
 !? ヽ::::ー-.. /ヽ ..ー-::: ヽ::| r--ッ 
-tヽ/´|`::::::::::;/   `、 ::::::::::: /: i }  > 
::∧: : :|: |J   \   /   /::i: | /_ゝ 
. \ヾ: |::|` - ,, ___`-´_ ,, - ´|: : :|:::| 
   ヽ: |::|\     ̄/ /|  |: : :|: | 


HTML5でOSを開発・・・。言葉の意味はよくわからないが何やらすごい新しい。これは自分でもぜひやってみたい。やるしか!

ということでやりました。まずはHTML5「で」プログラミング。Androidに使用しているプログラミング言語HTML5はきっとGoogleのトップシークレットだろうからとりあえず想像で。こんな感じかな・・・。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<script src="html5lang.js"></script>
</head>
<body autostart="true">
  <dfn title="greeting">
    <p name="name"></p>
    <code>
      <input name="message" />

      <dl name="name">
        <dt>HTML5</dt>
        <dd><fieldset name="message">Hello, <output name="name" /></fieldset></dd>
        <dt></dt>
        <dd><fieldset name="message">Good-bye, <output name="name" /></fieldset></dd>
      </dl>

      <blockquote cite="alert">
        <p><output name="message" /></p>
      </blockquote>
      <blockquote cite="log">
        <p><output name="message" /></p>
      </blockquote>
    </code>
  </dfn>

  <input name="name" value="HTML" />
  <progress name="counter" value="1" max="5">
    <blockquote cite="greeting">
      <p><output name="name"></output><output name="counter"></output></p>
    </blockquote>
  </progress>
</body>
</html>

文法はだいたいこんなん。

変数宣言 input要素
変数アクセス output要素
代入 fieldset要素
関数定義 dfn要素、p要素、code要素
関数呼出 blockquote要素、p要素
条件分岐 dl要素、dt要素、dd要素
繰り返し progress要素


変数宣言はHTML5のinputだから日付とか数値とか電話番号とかいろんな型が使用できる、はず。型チェックは実装してないけど。関数の引数はparam使いたかったなぁ・・・。でも無理っぽいのでpで妥協。あと関数呼び出しもcommandが名前的にはピッタリだったのに、HTML5は制限が厳しい・・・。条件分岐はselectとoptionで、てのも考えたけどoptionが子要素を持てないので挫折。defaultはselected="true"で、って思いついた時は自分は天才だと思ったのに・・・。余裕があればobject要素でクラス定義とかもやりたかったなぁ・・・。

そんな妥協にまみれた仕様だけど、まぁ現状でもなんとなく意味は取れるよね。

仮に、上のプログラミング言語HTML5ソースコードJavaScriptに書きなおせばこうなる。

function greeting(name) {
  var message;
  switch (name) {
    case 'HTML5':
      message = 'Hello, ' + name;
      break;
    default:
      message = 'Good-bye, ' + name;
      break;
  }
  window.alert(message);
  console.log(message);
}

var name = 'HTML';
for (var counter = 1; counter <= 5; counter++) {
  greeting(name + counter);
}


では、実行。

画面はこんな感じ。そこはどうでもいいんだけど。

実行結果。

よし動いた。

これでOS作るのか・・・。

そうか・・・。

・・・。


  イ`ヘ 
 /: :| ヽ 
/ : :/  ヽ ___   _,,,:. .-: :´彡フ 
_ノ\_∠: : : : : : : : :`: :-: :,:_:/彡 / 
      ( : : : : : : : : : : : : : : `ゝ  / 
  マ  r::/: /: : | : : : : : : : : ::\ / 
      //: /: : : |: : | |: : |: _: : : :ヽ 
  ジ  {/ 7|`\/i: /|:|/|´: : : : :|ヽ 
     〉 ,‐-‐、`|7 || |_::|,_|: : :|:::|: | 
  で / r:oヽ`    /.:oヽヽ: :|: | :| 
     { {o:::::::}     {:::::0 }/: :|N 
  っ  | ヾ:::ソ     ヾ:::ソ /|: : | 
 !? ヽ::::ー-.. /ヽ ..ー-::: ヽ::| r--ッ 
-tヽ/´|`::::::::::;/   `、 ::::::::::: /: i }  > 
::∧: : :|: |J   \   /   /::i: | /_ゝ 
. \ヾ: |::|` - ,, ___`-´_ ,, - ´|: : :|:::| 
   ヽ: |::|\     ̄/ /|  |: : :|: | 

*1:訂正済

インタネットベースのプログラミング言語HTML5

実行用のソースコードはこんな感じ。

window.log = function(msg) {console.log(msg)};

window.addEventListener('load', function() {
  var stack = [{vars:{}, funcs:{}}];

  function topContext() {
    return stack[stack.length - 1];
  }

  function readParam(node) {
    var ret = '';
    for (var i = 0; i < node.childNodes.length; i++) {
      var child = node.childNodes[i];
      if (child.nodeType == document.TEXT_NODE) {
        ret += child.nodeValue;
      }
      else if (child.nodeName == 'OUTPUT') {
        ret += topContext().vars[child.getAttribute('name')];
      }
    }
    return ret;
  }

  function callFunc(name, args) {
    var vars = {};
    var def = topContext().funcs[name];
    var code;
    for (var i = 0; i < def.childNodes.length; i++) {
      var child = def.childNodes[i];
      if (child.tagName == 'P') {
        vars[child.getAttribute('name')] = args.shift();
      }
      else if (child.tagName == 'CODE') {
        code = child;
      } 
    }   
    stack.push({vars:vars, funcs:{}});
    interprete(code);
    stack.pop();
  }

  function interprete(node) {
    if (!node) node = document.body;
    if (node.nodeName == 'BODY') {
      for (var i = 0; i < node.childNodes.length; i++) {
        interprete(node.childNodes[i]);
      }
    }
    else if (node.nodeName == 'INPUT') {
      topContext().vars[node.name] = node.value;
    }
    else if (node.nodeName == 'FIELDSET') {
      val = readParam(node);
      topContext().vars[node.getAttribute('name')] = val;
    }
    else if (node.nodeName == 'VAR' || node.nodeName == 'OUTPUT') {
    }
    else if (node.nodeName == 'DFN') {
      topContext().funcs[node.getAttribute('title')] = node;
    }
    else if (node.nodeName == 'CODE') {
      for (var i = 0; i < node.childNodes.length; i++) {
        interprete(node.childNodes[i]);
      }
    }
    else if (node.nodeName == 'BLOCKQUOTE') {
      var commandName = node.getAttribute('cite');
      var args = [];
      for (var i = 0; i < node.childNodes.length; i++) {
        var child = node.childNodes[i];
        if (child.nodeName == 'P') {
          args.push(readParam(child));
        }
      }
      if (window[commandName]) {
        // builtin function
        window[commandName].apply(window, args);
      }
      else {
        callFunc(commandName, args);
      }
    }
    else if (node.nodeName == 'DL') {
      var condition = topContext().vars[node.getAttribute('name')];
outer:
      for (var i = 0; i < node.childNodes.length; i++) {
        var child = node.childNodes[i];
        if (child.nodeName == 'DT') {
          if (child.childNodes.length == 0  // default condition
            || child.innerHTML == condition) {
            for (var j = i + 1; j < node.childNodes.length; j++) {
              var grandChild = node.childNodes[j];
              if (grandChild.nodeName == 'DD') {
                for (var k = 0; k < grandChild.childNodes.length; k++) {
                  interprete(grandChild.childNodes[k]);
                  break outer;
                }
              }
            }
          }
        }
      }
    }
    else if (node.nodeName == 'PROGRESS') {
      var counter = node.getAttribute('name')
      var min = node.getAttribute('value') || 0;
      var max = node.getAttribute('max');
      for (var i = min; i <= max; i++) {
        topContext().vars[counter] = i;
        for (var j = 0; j < node.childNodes.length; j++) {
          interprete(node.childNodes[j]);
        }
      }
    }
  }
  if (document.body.getAttribute('autostart')) {
    interprete();
  }
});