More Related Content
PPTX
CEDEC2021 ダウンロード時間を大幅減!~大量のアセットをさばく高速な実装と運用事例の共有~ SEGADevTech
PDF
なぜ、PHPのmbstring.func_overloadをdeprecatedにするのに5年かかったのか? - 慢心、環境の違い sasezaki
What's hot (14)
PDF
Windows で拡張モジュールをビルドしてみたy-uti
PDF
Web デザイナーが身に付けておきたい定番スキル ーPHP 初級編ーKite Koga
PDF
PECL operator で演算子オーバーロードy-uti
PDF
Mobage Connect と Identity 関連技術への取り組み - OpenID Summit Tokyo 2015Toru Yamaguchi
Similar to Power shell で DSL (20)
PPTX
Powershell 超絶基礎 勉強会 v1 (もっと新しいバージョンがあります)Tetsu Yama
Recently uploaded (11)
PPTX
2025_7_25_吉祥寺_設計ナイト_ADR運用におけるデータ利活用の考え方.pptxssuserfcafd1
Power shell で DSL
- 1. PowerShell で
、
C# で書かれたメソッドの JIT をフックする C++ のライブラリの
コードを自動生成するテンプレートエンジンのための
DSL
を実装してみた
杉浦 彰
Twitter: @urasandesu
Blog: http://urasandesu.blogspot.jp/
- 4. 自己紹介
オンラインでの活動(続き)
Prig(Prototyping jig)
C# (に限らず、.NET 上で動作する言語)で書かれたプログラムの JIT をフックし
て、実行時に処理を入れ替える。
構想含めると 5 年近く、7 回ほど作り直ししてますが、まだ動きません・・・。
単体テストのためのテストダブル生成フレームワーク。
やっと入れ替え前のメソッドの中身をコピーして、それを使って上書きして、元の
処理がそのまま動くよね、ってところ。
似たようなことができるもの
Microsoft Fakes/Typemock Isolator/Telerik JustMock
今回の PowerShell 勉強会のネタにはなりました!
- 6. DSL とは?
ドメイン特化言語(英: domain-specific programming language)
特定のタスク向けに設計されたコンピュータ言語。
一種類のタスクをうまく実行することに集中。
ポリシー
その領域(ドメイン)をより表現しやすくする。
そのドメインにおいては、仕様変更に対して最小限の記述で済ませられる。
包括的ではない。
- 15. 自作ライブラリ紹介
PSAnonym.Linq
PowerShell で LINQ っぽいものを書けるようにするモジュール。
PowerShell 2.0 でよく上げられる Select-Object の -First スイッチ問題や、
フロー制御構文の外で break を記述すると、スクリプト全体が止まってし
まう問題の解決が動機。
よく使うクエリ(Select/SelectMany/Where/Skip/Take/Any/Zip など)
を中心に、現在 27 クエリを実装。
例
PS ~> QRange 1 10 | QSelect { $1 * $1 } | QToArray
1
4
9
16
25
36
49
64
81
100
- 16. 自作ライブラリ紹介
PSAnonym.Prototype
PowerShell を、プロトタイプベース&多重継承サポートなオブジェクト指
向言語として使えるようにするモジュール。
PowerShell も DSL の一つ。クラス定義などは本来不要。
テンプレートエンジンに、PowerShell の強力なテキスト処理系はもってこ
い。しかし、実際に使うには、「状態を持ち、自分自身を操作できる」、
「基底 – 派生関係を持ち、生成の対象によって一部の振る舞いを変えるこ
とができる」といったクラスのような存在が欲しくなる。
例
PS ~> $animal1 = Prototype Animal | AbstractMethod Cry
PS ~> $dog1 = $animal1 | Prototype Dog | OverrideMethod Cry { 'わんわん' }
PS ~> $cat1 = $animal1 | Prototype Cat | OverrideMethod Cry { 'にゃーにゃー' }
PS ~> $chimaira1 = $dog1, $cat1 | Prototype Chimaira -Force |
>>
OverrideMethod Cry { $Dog.Cry() + $Cat.Cry() }
PS ~> $animals = $dog1, $cat1, $chimaira1
PS ~> $animals | % { $_.Cry() }
わんわん
にゃーにゃー
わんわんにゃーにゃー
- 18. 自作ライブラリ紹介
# ----------------------------------------------------------------------------------------------#
Swathe.ps1
# Declaration
#
Import SimpleHeapProvider
Import SmartHeapProvider
依存関係の定義ファイル
Import PersistableHeapProvider
・・・
Declare $RootDirectory Urasandesu Swathe / Hosting BaseClass / Base HostInfo / Fwd .h
Declare $RootDirectory Urasandesu Swathe / Hosting BaseClass / Base HostInfo / / .h
Declare $RootDirectory Urasandesu Swathe / Hosting BaseClass / Base HostInfo / / .hpp
Declare $RootDirectory Urasandesu Swathe AutoGen Hosting BaseClass / Base HostInfo / / .cpp
・・・
#
# ----------------------------------------------------------------------------------------------# ----------------------------------------------------------------------------------------------#
# Dependency
#
DependsOn BaseHostInfoFwdH DefaultHostInfoApiHolderFwdH
DependsOn BaseHostInfoH HostInfoFacadeH BaseHostInfoFwdH
DependsOn BaseHostInfoHpp BaseHostInfoH
DependsOn BaseHostInfoCpp BaseHostInfoHpp DefaultHostInfoApiHolderH DefaultHostInfoPimplApiHolderH
・・・
#
# -----------------------------------------------------------------------------------------------
- 19. 自作ライブラリ紹介
*Fwdh.Template.ps1
@"
#pragma once
#ifndef $($Me.IncludeGuard)
#define $($Me.IncludeGuard)
"@ + $({ $Me.DependentHeadersWithoutCommon } | QSelect { @"
#ifndef $($1.IncludeGuard)
#include <$($1.PathWithoutRoot)>
#endif
"@ } | QToParagraphParagraph) + @"
*h.Template.ps1
*hpp.Template.ps1
*cpp.Template.ps1
テンプレートファイル
namespace $($Me.Namespaces[0]) { namespace $($Me.Namespaces[1]) { namespace $($Me.Function) {
template<class ApiHolder>
class $($Me.Name)
{
public:
$($Me.ClassFacadeH.BeginTypedefAlias)
$($Me.ClassFacadeH.DeclareTypedefAlias)
$($Me.ClassFacadeH.EndTypedefAlias)
・・・
};
}}}}
#endif
"@
// namespace $($Me.Namespaces[0]) { namespace $($Me.Namespaces[1]) { namespace $($Me.Function) {
// $($Me.IncludeGuard)
- 20. 自作ライブラリ紹介
*Fwd.h
*.h
#pragma once
#ifndef URASANDESU_SWATHE_HOSTING_BASECLASS_BASEHOSTINFO_H
#define URASANDESU_SWATHE_HOSTING_BASECLASS_BASEHOSTINFO_H
#ifndef URASANDESU_SWATHE_AUTOGEN_HOSTING_CLASSFACADE_HOSTINFOFACADE_H
#include <Urasandesu/Swathe/AutoGen/Hosting/ClassFacade/HostInfoFacade.h>
#endif
#ifndef URASANDESU_SWATHE_HOSTING_BASECLASS_BASEHOSTINFOFWD_H
#include <Urasandesu/Swathe/Hosting/BaseClass/BaseHostInfoFwd.h>
#endif
namespace Urasandesu { namespace Swathe { namespace Hosting {
template<class ApiHolder>
class BaseHostInfo
{
public:
SWATHE_BEGIN_HOST_INFO_FACADE_TYPEDEF_ALIAS
SWATHE_DECLARE_HOST_INFO_FACADE_TYPEDEF_ALIAS
SWATHE_END_HOST_INFO_FACADE_TYPEDEF_ALIAS
・・・
};
}}}}
#endif
// namespace Urasandesu { namespace Swathe { namespace Hosting {
// URASANDESU_SWATHE_HOSTING_BASECLASS_BASEHOSTINFO_H
*.hpp
*.cpp
C++ ヘッダー/実装ファイル
- 21. 自作ライブラリ紹介
xx.vcxproj
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
VC++
・・・
<ItemGroup>
<ClCompile Include="UrasandesuSwatheAutoGenHostingBaseClassBaseHostInfo.cpp" />
・・・
</ItemGroup>
<ItemGroup>
<ClInclude Include="UrasandesuSwatheHostingBaseClassBaseHostInfo.h" />
<ClInclude Include="UrasandesuSwatheHostingBaseClassBaseHostInfo.hpp" />
<ClInclude Include="UrasandesuSwatheHostingBaseClassBaseHostInfoFwd.h" />
・・・
</ItemGroup>
</Project>
xx.vcxproj.filters
プロジェクトファイル
- 23. 私のケース
なぜこんなものを?
Prig は C++ がメイン開発言語。
マネージコードの JIT をフックするので、直接マネージコードを使うことはできない。
最初からある程度の規模を予想。
上記のものについて、生存期間が同じもの達に対して、その管理クラスを・・・。
さらにメモリ管理もある程度グルーピングして、その生成・破棄クラスを・・・。
主なクラス・・・ランタイムを動かすホスト、PE ファイルのリーダー/ライター、ラ
ンタイム情報へのアクセッサ、GAC とのやりとりを行う各種クラス、メタデータ情
報を表す各種クラス(Assembly/Module/Type/Method/Field/Property/Event
…)、プロファイリング情報を表す各種クラス、厳密な名前を扱うための各種クラ
ス、・・・。
あれ?1,000 クラスとか普通に超えるんじゃね?
ヘッダーファイルと実装ファイル間の依存関係をうまく管理できないと詰む!
- 24. 私のケース
C++ の依存関係のおさらい
コンパイル単位につき、
宣言はいくつでも
定義は 1 つ
#include の順番に依存
するのはまずい
インクルードガード
✔一意になるよう
に!
ファイルパスや名前空間から生成する
のが良いみたい
#pragma once
#ifndef URASANDESU_SWATHE_HOSTING_BASECLASS_BASEHOSTINFO_H
#define URASANDESU_SWATHE_HOSTING_BASECLASS_BASEHOSTINFO_H
#ifndef URASANDESU_SWATHE_HOSTING_BASECLASS_BASEHOSTINFOFWD_H
#include <Urasandesu/Swathe/Hosting/BaseClass/BaseHostInfoFwd.h>
#endif
namespace Urasandesu { namespace Swathe { namespace Hosting {
template<class ApiHolder>
class BaseHostInfo
{
・・・
};
}}}}
#endif
// namespace Urasandesu { namespace Swathe { namespace Hosting {
// URASANDESU_SWATHE_HOSTING_BASECLASS_BASEHOSTINFO_H
- 25. 私のケース
簡単にヘッダーファイル/実装ファイル間の依存関係管理できるツールって無い?
Microsoft :Visual C++ 開発用ツール/依存関係グラフ
C コードおよび C++ コードに対する依存関係グラフの生成機能!
Visual Studio Ultimate が必要。個人で使うには
・・・(´・ω・`)
GNU project: gcc
-MD スイッチで、依存関係一覧を make 向けのフォーマットで出力可能!
変更しても書き戻せない
・・・(´・ω・`)
Eclipse : C/C++ Development Tooling (CDT)
今調べると、Java の “Organize Imports” みたいな感じで、”Organize Includes”
ができるようになってる!?
うまく動かせず
・・・(´・ω・`)
- 29. PowerShell と DSL
PowerShell インアクション
Soul of a New Language
言語デザイナーの一人でもある
Bruce Payette が解説。
ポリシーや、なぜこうなってるの
かが記載してあり納得感。
第8章 スクリプトブロックとオブ
ジェクト には、「メタプログラミ
ング」や「言語の拡張」といった
心躍る内容がヾ(゚∀゚)ノ