От: | FDSC | consp11.github.io блог | |
Дата: | 05.08.11 23:32 | ||
Оценка: |
using Nemerle.Collections;
using Nemerle.Text;
using Nemerle.Utility;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace marks
{
// Этим макросом пытаемся поставить метку на AST
macro verificationMarkLogic (vlMarkName, logicTest, body)
syntax ("vlMark", "(", vlMarkName, logicTest, ")", body)
{
// Делаем кортеж из данных метки и тела метода
def typle = vlMarkName::logicTest::body::[];
<[
def result = $(PExpr.Tuple.Create
(
typle
));
// Возвращаем результат вычисления метода
result[2]
]>
}
// Определяем макрос-атрибут метода
[Nemerle.MacroUsage (Nemerle.MacroPhase.WithTypedMembers,
Nemerle.MacroTargets.Method, Inherited = true)]
// У макроса должно быть два параметра:
// строка-имя состояния конечного автомата, в которое переводится автомат после выполнения данного метода
// и список допустимых состояний, в которых можно вызывать данный метод
macro verificationMarkState (tb : TypeBuilder, meth : MethodBuilder, vlStateName, vlAllowableStates)
{
// Если членов класса почему-то нет, то считаем это ошибкой
if (!tb.LookupMemberAvailable)
{
def msg = "lookup member not available for class $(tb.Name) in the macro verificationMarkState";
Message.Error(meth.Location, msg);
}
else
{
// Вводим служебную переменную
def serviceMemberName = tb.Name + "_verificationMark_state";
mutable flag = false;
when (tb.LookupMember (serviceMemberName) == [])
tb.Define (<[ decl: $serviceMemberName: string = "" ]>);
// Генерируем новое тело метода
def msg = "Not allowed state for class $(tb.Name) in method $(meth.Name)";
meth.Body =
<[
// Проверяем, что текущее состояние позволяет вызывать данный метод
def temporary_verification_flag = false;
foreach (allowableState in vlAllowableStates)
{
when ( $serviceMemberName == allowableState)
{
temporary_verification_flag = true;
break;
}
}
assert(temporary_verification_flag, $msg);
// Выполняем вычисления и меняем состояние, если не произошло исключение
$(meth.Body);
$serviceMemberName = $vlStateName;
]>
}
}
public partial class MainForm : Form
{
public this()
{
InitializeComponent();
}
private button1_Click (_ : object, _ : System.EventArgs) : void
{
markTest();
}
class File
{
[verificationMarkState("initialized", "":[])]
public this()
{
_ = MessageBox.Show("File");
}
[verificationMarkState("opened", "initialized":[])]
public open(): void
{
_ = MessageBox.Show("open");
}
public doing(): void
{
_ = MessageBox.Show("doing");
}
[verificationMarkState("closed", "opened":[])]
public close(): void
{
_ = MessageBox.Show("Close");
}
}
public markTest(): void
{
def f = File();
f.open();
f.doing();
f.close();
f.close();
}
}
}
Build FAILED.
"D:\works\programming\AITryes\macroTryes\marks\marks.nproj" (Build target) (1)
->
(CoreCompile target) ->
MainForm.n(97,10,97,53): error : the custom attribute `verificationMarkState(
"initialized", ("" : []))' could not be found or is invalid [D:\works\programmi
ng\AITryes\macroTryes\marks\marks.nproj]
0 Warning(s)
1 Error(s)
Time Elapsed 00:00:00.83