-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathFilterReader.boo
60 lines (50 loc) · 2.27 KB
/
FilterReader.boo
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
namespace TURBU.RubyMarshal.Reader
import System
import System.Collections.Generic
import System.Linq.Enumerable
import Boo.Lang.Compiler.Ast
macro Filter(name as string):
macro Any:
ValidateMacro(Any)
var expr = ExpressionChain(FragmentsFor(Any), BinaryOperatorType.Or)
ParentFragments(Any).Add(expr)
macro All:
ValidateMacro(All)
var expr = ExpressionChain(FragmentsFor(All), BinaryOperatorType.And)
ParentFragments(All).Add(expr)
macro Code(id as int):
var fragments = ParentFragments(Code)
fragments.Add([|c.Code == $id|])
macro Value(data as BinaryExpression):
raise "Value expression must begin with an integer" unless data.Left isa IntegerLiteralExpression
data.Operator = BinaryOperatorType.Equality if data.Operator == BinaryOperatorType.Assign
left as Expression = [|c.Params[$(data.Left)]|]
if data.Right.Matches([|Target|]) or data.Right isa IntegerLiteralExpression:
left = [| $left cast int |]
elif data.Right isa StringLiteralExpression:
left = [| $left cast string |]
data = BinaryExpression(data.Operator, left, data.Right)
var fragments = ParentFragments(Value)
fragments.Add(data)
ValidateMacro(Filter)
fragments as List[of Expression] = Filter['fragments']
raise "A filter must contain at least one filter expression" if fragments.Count == 0
expr as Expression = fragments[0]
for sub in fragments.Skip(1):
expr = [|$expr and $sub|]
return ExpressionStatement([|AddFilter($name, {c as TURBU.RubyMarshal.XPEventCommand, Target as int | return $expr} )|])
internal def ExpressionChain(fragments as Expression*, operator as BinaryOperatorType) as Expression:
result as Expression = null
for expr in fragments:
result = (expr if result is null else BinaryExpression(operator, result, expr))
return result
internal def FragmentsFor(node as MacroStatement) as List of Expression:
fragments as List[of Expression] = node['fragments']
if fragments is null:
fragments = List[of Expression]()
node['fragments'] = fragments
return fragments
internal def ParentFragments(node as MacroStatement) as List of Expression:
return FragmentsFor(node.GetAncestor[of MacroStatement]())
internal def ValidateMacro(node as MacroStatement):
raise "Only Code, Value, Any and All expressions are allowed in a filter" unless node.Body.Statements.Count == 0