CoffeeScriptで、テンプレートエンジン用にevalで変数展開


evalで変数展開

やばいけど、ローカルツールならいいよねえ。strictモードだと、これは使えません。第三者が実行できるコードだととてもやばいです。でも、構文解析とかせずとも、Javascriptの構文が使えて楽ちんなのです。

express-generatorはどうしてるんだろう、と思ったら、オプション毎に一々雛形を作っていました。ちぇ。やはり割とパブリックなツールだと、そういうところは真面目なのね。

template.coffee
templatecopyfile = (__dstpath__, __srcpath__, __dstfile__, __srcfile__, __param__) ->
  #予約語をオブジェクトに入れるよ。CoffeeScriptをコンパイルすると、
  #使用している変数を冒頭でまとめて宣言してくれるので、そこからコピペすればOK
  # i とか len とか勝手に作っているのが分かるね。
  __reserved__ =
    __reserved__:true
    __dstpath__:true
    __srcpath__:true
    __dstfile__:true
    __srcfile__:true
    __param__:true
    __detail__:true
    __inputlines__:true
    __key__:true
    __line__:true
    __linenumber__:true
    __result__:true
    __resultlines__:true
    __scanscope__:true
    __script__:true
    __stack__:true
    __usekey__:true
    __usescope__:true
    __usevalue__:true
    __value__:true
    __whenvalue__:true
    i:true
    len:true

  #予約語判定して、変数をローカルに展開するよ
  for __key__,__value__ of __param__
    if __key__ in __reserved__
      console.log 'a variable name ['+__key__+'] is reserved.'
      process.exit 1
    else
      eval 'var '+__key__+' = __value__;'


  ###
     中略
  ###


  #変数を使うときは、がっつりevalしちゃうよ
  if /^switch\s+(\S.*)$/.test(__script__)
    __detail__ = __script__.match(/^switch\s+(\S.*)$/)
    __stack__.push()
    __stack__[__stack__.length-1].mode = 'switch'
    __stack__[__stack__.length-1].value = eval __detail__[1]
    __stack__[__stack__.length-1].phase = null
    __stack__[__stack__.length-1].matched = false
    __stack__[__stack__.length-1].usescope = false