
コンピュータプログラミングにおいて、マクロ(「マクロ命令」の略。ギリシャ語のμακρο - 「長い、大きい」[ 1 ]に由来)とは、特定の入力を代替出力にどのようにマッピングするかを指定する規則またはパターンです。入力にマクロを適用することは、マクロ展開として知られています。
入力と出力は、字句トークンまたは文字のシーケンス、あるいは構文木となる場合があります。ソフトウェアアプリケーションでは、一般的なコマンドシーケンスを簡単に呼び出せるように、文字マクロがサポートされています。一部のプログラミング言語では、コードの再利用や言語の拡張を可能にするために、トークンマクロとツリーマクロがサポートされており、ドメイン固有言語の場合にも使用されることがあります。
マクロは、一連の計算命令を単一のプログラムステートメントとしてプログラマに提供するために使用され、プログラミング作業をより面倒でエラーの少ないものにします。[ 2 ] [ 3 ]そのため、「小さな」文字のシーケンスから「大きな」コードブロックを展開できることから、「マクロ」と呼ばれています。マクロは多くの場合、条件付きアセンブラプログラムが生成するものを決定する位置パラメータまたはキーワード パラメータを許可し、オペレーティングシステム、プラットフォーム、その他の要因などの変数に応じてプログラム全体またはプログラム スイートを作成するために使用されてきました。この用語は「マクロ命令」に由来し、このような展開は元々アセンブリ言語コードの生成に使用されていました。
キーボードマクロとマウスマクロを使用すると、短いキーストロークとマウス操作のシーケンスを、通常はより時間のかかる別のキーストロークとマウス操作のシーケンスに変換できます。このようにして、頻繁に使用される、または繰り返されるキーストロークとマウス操作のシーケンスを自動化できます。これらのマクロを作成するための個別のプログラムは、マクロレコーダーと呼ばれます。[ 4 ]
1980年代には、マクロプログラム (当初はSmartKey、その後SuperKey、KeyWorks、Prokeyなど)が非常に人気を博しました。当初は脚本 の自動フォーマット手段として、その後は様々なユーザー入力タスクに利用されました。これらのプログラムは、終了後も常駐する動作モードに基づいており、どのような状況下でもすべてのキーボード入力に適用されました。しかし、マウス操作によるユーザーインターフェースの登場や、ワープロソフトや表計算ソフトなどのアプリケーションにおけるキーボードおよびマウスマクロの導入により、アプリケーション固有のキーボードマクロを作成できるようになったことで、マクロプログラムは次第に時代遅れになっていきました。
キーボードマクロは、大規模マルチプレイヤーオンラインロールプレイングゲーム(MMORPG)で、反復的ではあるものの収益性の高いタスクを実行するために使用され、それによってリソースを蓄積することができます。これは人間の労力なしで行われるため、ゲームの経済を歪める可能性があります。このため、マクロの使用はほとんどのMMORPGの利用規約またはEULAに違反しており、管理者はマクロの抑制に多大な労力を費やしています。[ 5 ]
アプリケーションの組み込みマクロ機能を使用して作成されるキーボードおよびマウスのマクロは、アプリケーションマクロと呼ばれることがあります。これらは、一連の操作を一度実行し、アプリケーションにその動作を記録させることで作成されます。アプリケーションの機能に直接アクセスできる、基盤となるマクロプログラミング言語(最も一般的なのはスクリプト言語)が存在する場合もあります。[ 6 ]
プログラマー向けのテキストエディタであるEmacs(「editing macros」の略)はこの考え方を極限まで推し進めている。実際、エディタの大部分はマクロで構成されている。Emacsは元々、編集言語TECOのマクロセットとして考案され、後にLispの方言に移植された。[ 7 ]
プログラマー向けのテキストエディタであるVim ( viの後継) も、キーボードマクロを実装しています。キーボードで入力した内容をレジスタ (マクロ) に記録し、 Microsoft Office のVBAマクロのように再生したり編集したりできます。Vim には、マクロを作成するためのVimscript [ 8 ]と呼ばれるスクリプト言語もあります。
Visual Basic for Applications (VBA) は、 Microsoft Office 97 から Office 2019 まで搭載されているプログラミング言語です(ただし、Office 97 以前の Office の一部のコンポーネントにも含まれていました)。しかし、その機能は、これらのアプリケーションに当初含まれていたマクロ言語から進化し、それらに取って代わるようになりました。
VMの会話モニタ システム(CMS) コンポーネント上で動作するXEDIT は、 EXEC、EXEC2、およびREXXで記述されたマクロをサポートしており、一部の CMS コマンドは実際には XEDIT マクロのラッパーでした。XEDITの部分的なクローンであるHessling Editor (THE) は、Regina および Open Object REXX (oorexx)を使用して Rexx マクロをサポートしています。多くの一般的なアプリケーション、および PC 上の一部のアプリケーションは、スクリプト言語として Rexx を使用しています。[ 9 ]
VBAはほとんどのMicrosoft Windowsシステムコールにアクセスでき、ドキュメントが開かれると実行されます。そのため、VBAでコンピュータウイルス(一般にマクロウイルスと呼ばれる)を作成するのは比較的容易です。1990年代半ばから後半にかけて、これは最も一般的なコンピュータウイルスの1つとなりました。しかし、1990年代後半から現在に至るまで、Microsoftはプログラムのパッチ適用と更新を継続的に行っています。さらに、最新のウイルス対策ソフトは、このような攻撃に即座に対応します。
パラメータ付きマクロとは、指定されたオブジェクトを展開に挿入できるマクロのことです。これにより、マクロは関数のような強力な機能を持つようになります。
簡単な例として、C言語では、これはパラメータ付きマクロではない、つまりパラメータなしマクロの典型的な例です。
#define PI 3.14159
これにより、出現する箇所すべてPIで常に置き換えられます3.14159。一方、パラメータ付きマクロの例は次のとおりです。
#define pred(x) ((x)-1)
このマクロが展開される内容は、渡される引数xによって異なります。以下に、考えられる展開例をいくつか示します。
pred(2) → ((2) -1) pred(y+2) → ((y+2) -1) pred(f(5)) → ((f(5))-1)
パラメータ付きマクロは、インライン展開を実行するための便利なソースレベルのメカニズムですが、単純なテキスト置換を使用するCなどの言語では、インライン関数などの他のインライン展開を実行するメカニズムに比べて、多くの深刻な欠点があります。
一方、Lisp、PL/I、Schemeなどの言語で使用されるパラメータ付きマクロは、引数に基づいて生成するコードを決定することができるため、はるかに強力です。したがって、実行時コード生成を効果的に実行するために使用できます。
C言語や一部のアセンブリ言語には、コンパイラやアセンブラのプリプロセッサとして実装された基本的なマクロシステムがあります。C言語のプリプロセッサマクロは、文字レベルではなくトークンレベルでの単純なテキスト置換によって機能します。しかし、 IBM High Level Assembler (HLASM) のようなより高度なアセンブラのマクロ機能は、プリプロセッサでは実装できません。命令とデータのアセンブリコードとマクロ呼び出しのアセンブリコードが混在しているためです。
マクロの典型的な使用例は、コンピュータ組版システムTeXとその派生システムであり、その機能のほとんどはマクロに基づいています。[ 10 ]
MacroMLは、静的型付けとマクロシステムを調和させようとする実験的なシステムです。Nemerleには型付き構文マクロがあり、これらの構文マクロを考える生産的な方法の1つは、多段階の計算として捉えることです。
その他の例:
主要なアプリケーションの中には、他のアプリケーションから呼び出されるテキストマクロとして記述されているものもある。例えば、CMSのXEDITなどがその例である。
PHPなどの一部の言語は、自由形式のテキストや他の言語のソースコードに埋め込むことができます。コード断片を認識する仕組み(例えば、`<code><input type="code">`と`<code><input type="code">`で囲むなど<?php)?>はテキストマクロ言語に似ていますが、PHPなどの言語ははるかに強力で、機能も充実しています。
PL/I言語のマクロは、PL/I 言語自体のサブセットで記述されます。コンパイラはコンパイル時に「プリプロセッサステートメント」を実行し、この実行結果がコンパイルされるコードの一部となります。使い慣れた手続き型言語をマクロ言語として使用できることで、テキスト置換マクロよりもはるかに強力な機能を実現できますが、コンパイラのサイズが大きくなり、処理速度も遅くなります。PL/I のマクロは、多くのアセンブラと同様に、他のマクロがアクセスできる変数を設定するなど、副作用を持つ場合があります。
フレーム技術のフレームマクロは独自のコマンド構文を持ちますが、任意の言語のテキストを含めることもできます。各フレームは、ネストされたサブアセンブリの階層における汎用コンポーネントであると同時に、サブアセンブリフレームとの統合手順でもあります(統合の競合を上位レベルのサブアセンブリを優先して解決する再帰的なプロセス)。出力はカスタムドキュメントであり、通常はコンパイル可能なソースモジュールです。フレーム技術は、マクロとサブルーチンの発明以来ソフトウェア開発を悩ませてきた、類似しているが微妙に異なるコンポーネントの乱立を防ぐことができます。
ほとんどのアセンブリ言語には、ループ展開のためにコードブロックをN回繰り返すことができるなど、それほど強力ではない手続き型マクロ機能がありますが、これらは実際のアセンブリ言語とは全く異なる構文を持っています。
先に述べたC言語のプリプロセッサのような、字句レベルで動作するマクロシステムは、字句構造を確実に保持することができません。一方、構文マクロシステムは抽象構文木のレベルで動作し、元のプログラムの字句構造を保持します。構文マクロシステムの最も広く使われている実装は、Lisp系の言語に見られます。これらの言語は、括弧で囲まれた統一的な構文( S式と呼ばれる)を持つため、このスタイルのマクロに特に適しています。特に、統一された構文によってマクロの呼び出しを容易に特定できます。Lispマクロはプログラム構造自体を変換し、そのような変換を表現するために言語全体を利用できます。構文マクロは Lisp 系言語によく見られますが、Prolog [ 11 ] Erlang [ 12 ] Dylan [ 13 ] Scala [ 14 ] Nemerle [ 15 ] Rust [ 16 ] Elixir [ 17 ] Nim [ 18 ] Haxe [ 19 ]やJulia [ 20 ]などの他の言語でも利用できます。また、JavaScript [ 21 ]やC# [ 22 ]のサードパーティ拡張機能としても利用できます。
Lispにマクロが導入される以前は、いわゆるFEXPRと呼ばれる関数のような演算子がありました。FEXPRは、入力が引数によって計算される値ではなく、引数の構文形式であり、出力は計算に使用される値でした。言い換えれば、FEXPRはEVALと同じレベルで実装され、メタ評価層への窓を提供しました。これは一般的に、効果的に推論するのが難しいモデルであることがわかりました。[ 23 ]
1963年、ティモシー・ハートはAIメモ57「LISPのマクロ定義」でLisp 1.5にマクロを追加することを提案した。[ 24 ]
照応マクロとは、マクロに渡された何らかの形式を意図的にキャプチャし、それを照応(別の式を参照する表現)によって参照できるようにするプログラミングマクロの一種です。照応マクロは、ポール・グラハムの著書『On Lisp』で初めて登場し、その名称は言語における照応(先行する語の代わりに別の語を用いる表現)に由来しています。
1980年代半ば、いくつかの論文[ 25 ] [ 26 ]で、マクロ定義とマクロ使用の構文環境が区別されるパターンベースのシステムである衛生的マクロ展開( )の概念が導入され、マクロ定義者と使用者は意図しない変数キャプチャ(参照透過性参照)を心配する必要がなくなりました。衛生的マクロは、 R5RS、R6RS、およびR7RS標準でScheme向けに標準化されています。衛生的マクロの競合する実装には、、、明示的な名前変更、構文クロージャなどがあります。と両方はScheme標準で標準化されています。syntax-rulessyntax-rulessyntax-casesyntax-rulessyntax-case
最近、Racketは衛生的なマクロの概念と「評価器のタワー」を組み合わせ、あるマクロシステムの構文展開時間が別のコードブロックの通常の実行時間になるようにしました[ 27 ]。また、括弧のない言語でインターリーブ展開と構文解析を適用する方法を示しました[ 28 ] 。
Scheme以外の多くの言語は、衛生的なマクロを実装しているか、部分的に衛生的なシステムを実装しています。例としては、Scala、Rust、Elixir、Julia、Dylan、Nim、Nemerleなどが挙げられます。
condなど)を作成できます。たとえば、継続はあるものの継続がないLisp方言ではif、マクロを使用して継続を前者で定義できます。たとえば、Schemeには継続と衛生マクロの両方があり、プログラマはループや早期終了構造などの独自の制御抽象化を、言語に組み込むことなく設計できます。let関数を引数のセットに適用する形に変換することです。フェライゼンは[ 30 ] 、これら3つのカテゴリーがそのようなシステムにおけるマクロの主要な正当な使用法を構成していると推測している。他の研究者は、マクロシステムの不衛生なアナフォリックマクロや、選択的な不衛生な変換を可能にするマクロなど、マクロの代替的な使用法を提案している。
マクロと他の言語機能との相互作用は、活発な研究分野となっています。例えば、コンポーネントやモジュールは大規模なプログラミングに役立ちますが、マクロとこれらの他の構成要素との相互作用は、それらを一緒に使用するために定義する必要があります。Schemeやその他のマクロを持つ言語では、マクロと相互作用できるモジュールシステムやコンポーネントシステムが提案されています。例えば、Racket言語はマクロシステムの概念を構文タワーに拡張しており、マクロを含む言語でマクロを記述でき、衛生的な方法を用いて構文レイヤーが明確に区別されるようにし、モジュールが他のモジュールにマクロをエクスポートできるようにしています。
マクロは通常、短い文字列(マクロ呼び出し)をより長い命令シーケンスにマッピングするために使用されます。マクロのもう1つの、あまり一般的ではない使用法は、その逆、つまり命令シーケンスをマクロ文字列にマッピングすることです。これは、STAGE2モバイルプログラミングシステムで採用されたアプローチで、基本的なマクロコンパイラ(SIMCMPと呼ばれる)を使用して、特定のコンピュータの特定の命令セットをマシン非依存のマクロにマッピングします。これらのマシン非依存のマクロで記述されたアプリケーション(特にコンパイラ)は、基本的なマクロコンパイラを備えたどのコンピュータでも変更せずに実行できます。このようなコンテキストで最初に実行されるアプリケーションは、マシン非依存のマクロ言語で記述された、より高度で強力なマクロコンパイラです。このマクロコンパイラは、ブートストラップ方式で自身に適用され、コンパイルされた、はるかに効率的なバージョンが生成されます。このアプローチの利点は、複雑なアプリケーションを、非常に少ない労力で(各ターゲットマシンアーキテクチャに対して、基本的なマクロコンパイラを記述するだけで)あるコンピュータからまったく異なるコンピュータに移植できることです。[ 31 ] [ 32 ]現代のプログラミング言語、特にC言語の登場により、ほぼすべてのコンピュータでコンパイラが利用可能になったため、このようなアプローチは不要になった。しかし、これはコンパイラブートストラップの最初の事例の1つ(最初の事例ではないかもしれない)であった。
マクロ命令は、プログラマが任意のネイティブアセンブラプログラム命令のセットに対して定義できますが、通常マクロはオペレーティングシステムに付属するマクロライブラリに関連付けられており、オペレーティングシステムの機能へのアクセスを可能にします。
IBMメインフレームなどで使用されていたような旧式のオペレーティングシステムでは、標準マクロ命令に対応するルーチンが必ずしも高水準言語で利用可能ではなかったため、オペレーティングシステムの全機能はアセンブリ言語プログラムでのみ利用可能であり、高水準言語プログラムでは利用できませんでした(もちろん、アセンブリ言語のサブルーチンを使用する場合は別です)。
1950年代半ば、アセンブリ言語プログラミングがコンピュータのプログラミングの主な方法であった時代には、ソースコードを削減するため(各マクロ命令から複数のアセンブリ文を生成することによって)、またコーディング規約を強制するため(例えば、入出力コマンドを標準的な方法で指定するなど)にマクロ命令機能が開発されました。 [ 35 ]アセンブリソースコードに埋め込まれたマクロ命令は、アセンブラのプリプロセッサであるマクロコンパイラによって処理され、マクロが1つ以上のアセンブリ命令に置き換えられます。結果として得られる純粋なアセンブリコードは、アセンブラによってマシンコードに変換されます。 [ 36 ]
IBM 705コンピュータ用のマクロ言語を開発するために初期に設置されたプログラミング施設のうち2つは、デラウェア州のダウ・ケミカル社と、カリフォルニア州の航空資材軍団弾道ミサイル兵站局にあった。
マクロ命令は、アセンブリ言語プログラミングと、 FORTRANやCOBOLといった後続の高級プログラミング言語との中間段階であると考える人もいる。
1950年代後半には、マクロ言語に続いてマクロアセンブラが登場しました。これは、1つのプログラムがマクロプリプロセッサとアセンブラの両方の機能を同じパッケージ内で果たすという、両者の組み合わせでした。[ 36 ]初期の例としては、 IBM 709、7094、7040、7044のFORTRAN Assembly Program (FAP) [ 37 ]と Macro Assembly Program (IBMAP) [ 38 ]、および7070/7072/7074のAutocoder [ 39 ]があります。
1959年、ベル研究所のダグラス・E・イーストウッドとダグラス・マッキルロイは、人気のSAPアセンブラに条件付きマクロと再帰マクロを導入し[ 40 ] 、マクロSAPとして知られるものを作り出した[ 41 ] 。マッキルロイの1960年の論文は、マクロプロセッサを介してあらゆる(高水準を含む)プログラミング言語を拡張する分野で先駆的なものとなった[ 42 ] [ 40 ]。
マクロアセンブラは、アセンブリ言語プログラマが独自のマクロ言語を実装することを可能にし、同じCPUを搭載しながらも異なるオペレーティングシステム(例えば、初期のMS-DOSとCP/M-86 )を搭載した2台のマシン間で、限定的なコードの移植性を実現しました。マクロライブラリは各ターゲットマシンごとに作成する必要がありましたが、アセンブリ言語プログラム全体を作成する必要はありませんでした。より強力なマクロアセンブラでは、マクロ命令内で条件付きアセンブリ構造を使用できるため、異なるマシンや異なるオペレーティングシステム上で異なるコードを生成でき、複数のライブラリの必要性を軽減できる点に留意してください。
1980年代から1990年代初頭にかけて、デスクトップPCのクロック速度はわずか数MHzで、C、Fortran、Pascalなどの言語で書かれたプログラムの高速化には、アセンブリ言語ルーチンが一般的に用いられていました。当時、これらの言語はそれぞれ異なる呼び出し規約を採用していました。マクロを用いることで、アセンブリ言語で書かれたルーチンを、ほぼあらゆる言語で書かれたアプリケーションのフロントエンドと連携させることが可能になりました。ここでも、基本的なアセンブリ言語コードは同じままで、各対象言語ごとにマクロライブラリを作成するだけで済みました。
Unixやその派生システムといった現代のオペレーティングシステムでは、オペレーティングシステムへのアクセスはサブルーチンを介して行われ、通常は動的ライブラリによって提供されます。C言語のような高水準言語はオペレーティングシステムの機能への包括的なアクセスを提供するため、そのような機能のためにアセンブリ言語プログラムを作成する必要がなくなります。
さらに、Goなどのいくつかの新しいプログラミング言語の標準ライブラリは、移植性とセキュリティを向上させるために、必要でない限りシステムコールの使用を積極的に抑制し、プラットフォームに依存しないライブラリを推奨しています。[ 43 ]
際の時間と事務的なエラーを削減することです。
TEX にはマクロ プログラミング言語があり、機能を追加できます。
{{cite web}}: CS1メンテナンス: アーカイブサービスは非推奨になりました (リンク)