RosettaCodeData/Task/Extend-your-language/Morfa/extend-your-language.morfa

78 lines
2.2 KiB
Plaintext

import morfa.base;
// introduce 4 new operators to handle the if2 syntax
operator then { kind = infix, precedence = mul, associativity = right}
operator else1 { kind = infix, precedence = not, associativity = left }
operator else2 { kind = infix, precedence = not, associativity = left }
operator none { kind = infix, precedence = not, associativity = left }
// function which bounds the condition expression to the if2 "actions"
public func then(condition: IF2.Condition, actionHolder: IF2): void
{
actionHolder.actions[condition]();
}
// functions (bound to operators) used to "build" the if2 "statement"
public func else1(bothAction: func(): void, else1Action: func(): void): IF2
{
return IF2([IF2.Condition.both -> bothAction,
IF2.Condition.else1 -> else1Action]);
}
public func else2(actionHolder: IF2, action: func(): void): IF2
{
return checkAndAdd(actionHolder, action, IF2.Condition.else2);
}
public func none(actionHolder: IF2, action: func(): void): IF2
{
return checkAndAdd(actionHolder, action, IF2.Condition.none);
}
// finally, function which combines two conditions into a "trigger" for the if2 "statement"
public func if2(condition1: bool, condition2: bool): IF2.Condition
{
if (condition1 and condition2)
return IF2.Condition.both;
else if (condition1)
return IF2.Condition.else1;
else if (condition2)
return IF2.Condition.else2;
else
return IF2.Condition.none;
}
// private helper function to build the IF2 structure
func checkAndAdd(actionHolder: IF2, action: func(): void, actionName: IF2.Condition): IF2
{
if (actionHolder.actions.contains(actionName))
throw new Exception("action defined twice for one condition in if2");
else
actionHolder.actions[actionName] = action;
return actionHolder;
}
// helper structure to process the if2 "statement"
struct IF2
{
public enum Condition { both, else1, else2, none };
public var actions: Dict<Condition, func(): void>;
}
// usage
if2 (true, false) then func()
{
println("both true");
}
else1 func()
{
println("first true");
}
else2 func()
{
println("second true");
}
none func()
{
println("none true");
};