Browse Source

Merge 9a7e936919 into 879c69874a

pull/2/merge
Ingo Struck 11 years ago
parent
commit
c2be9b0297
6 changed files with 198 additions and 42 deletions
  1. +130
    -0
      priv/edoc.css
  2. +9
    -3
      src/glc.erl
  3. +31
    -21
      src/glc_code.erl
  4. +2
    -0
      src/glc_lib.erl
  5. +25
    -17
      src/glc_ops.erl
  6. +1
    -1
      src/gre.erl

+ 130
- 0
priv/edoc.css View File

@ -0,0 +1,130 @@
/* Baseline rhythm */
body {
font-size: 16px;
font-family: Helvetica, sans-serif;
margin: 8px;
}
p {
font-size: 1em; /* 16px */
line-height: 1.5em; /* 24px */
margin: 0 0 1.5em 0;
}
h1 {
font-size: 1.5em; /* 24px */
line-height: 1em; /* 24px */
margin-top: 1em;
margin-bottom: 0em;
}
h2 {
font-size: 1.375em; /* 22px */
line-height: 1.0909em; /* 24px */
margin-top: 1.0909em;
margin-bottom: 0em;
}
h3 {
font-size: 1.25em; /* 20px */
line-height: 1.2em; /* 24px */
margin-top: 1.2em;
margin-bottom: 0em;
}
h4 {
font-size: 1.125em; /* 18px */
line-height: 1.3333em; /* 24px */
margin-top: 1.3333em;
margin-bottom: 0em;
}
.class-for-16px {
font-size: 1em; /* 16px */
line-height: 1.5em; /* 24px */
margin-top: 1.5em;
margin-bottom: 0em;
}
.class-for-14px {
font-size: 0.875em; /* 14px */
line-height: 1.7143em; /* 24px */
margin-top: 1.7143em;
margin-bottom: 0em;
}
ul {
margin: 0 0 1.5em 0;
}
/* Customizations */
body {
color: #333;
}
tt, code, pre {
font-family: "Andale Mono", "Inconsolata", "Monaco", "DejaVu Sans Mono", monospaced;
}
tt, code { font-size: 0.875em }
pre {
font-size: 0.875em; /* 14px */
line-height: 1.7143em; /* 24px */
margin: 0 1em 1.7143em;
padding: 0 1em;
background: #eee;
}
.navbar img, hr { display: none }
table {
border-collapse: collapse;
}
h1 {
border-left: 0.5em solid #fa0;
padding-left: 0.5em;
}
h2.indextitle {
font-size: 1.25em; /* 20px */
line-height: 1.2em; /* 24px */
margin: -8px -8px 0.6em;
background-color: #fa0;
color: white;
padding: 0.3em;
}
ul.index {
list-style: none;
margin-left: 0em;
padding-left: 0;
}
ul.index li {
display: inline;
padding-right: 0.75em
}
div.spec p {
margin-bottom: 0;
padding-left: 1.25em;
background-color: #eee;
}
h3.function {
border-left: 0.5em solid #fa0;
padding-left: 0.5em;
background: #fc9;
}
a, a:visited, a:hover, a:active { color: #C60 }
h2 a, h3 a { color: #333 }
i {
font-size: 0.875em; /* 14px */
line-height: 1.7143em; /* 24px */
margin-top: 1.7143em;
margin-bottom: 0em;
font-style: normal;
}

+ 9
- 3
src/glc.erl View File

@ -87,10 +87,16 @@
-record(module, {
'query' :: term(),
tables :: [{atom(), ets:tid()}],
tables :: [{atom(), ets:tab()}],
qtree :: term()
}).
-export_type([qry/0, action/0]).
%-type qry() :: {atom(), '*'|false|true|[any(),...]} | {atom(), '<'|'='|'>', _}.
-type qry() :: glc_ops:op().
-type action() :: fun((gre:event()) -> any()).
-spec lt(atom(), term()) -> glc_ops:op().
lt(Key, Term) ->
glc_ops:lt(Key, Term).
@ -140,7 +146,7 @@ null(Result) ->
%% Updating the output action of a query finalizes it. Attempting
%% to use a finalized query to construct a new query will result
%% in a `badarg' error.
-spec with(glc_ops:op(), fun((gre:event()) -> term())) -> glc_ops:op().
-spec with(Query::qry(), Action::action()) -> {with, Query::qry(), Action::action()}.
with(Query, Action) ->
glc_ops:with(Query, Action).
@ -165,7 +171,7 @@ union(Queries) ->
%% On success the module representing the query is returned. The module and
%% data associated with the query must be released using the {@link delete/1}
%% function. The name of the query module is expected to be unique.
-spec compile(atom(), list()) -> {ok, atom()}.
-spec compile(Module :: atom(), Query :: qry()) -> {ok, atom()}.
compile(Module, Query) ->
{ok, ModuleData} = module_data(Query),
case glc_code:compile(Module, ModuleData) of

+ 31
- 21
src/glc_code.erl View File

@ -9,9 +9,10 @@
-record(module, {
'query' :: term(),
tables :: [{atom(), ets:tid()}],
tables :: [{atom(), ets:tab()}],
qtree :: term()
}).
-type mod() :: #module{}.
-type syntaxTree() :: erl_syntax:syntaxTree().
@ -20,11 +21,12 @@
fields = [] :: [{atom(), syntaxTree()}],
fieldc = 0 :: non_neg_integer(),
paramvars = [] :: [{term(), syntaxTree()}],
paramstab = undefined :: ets:tid()
paramstab = undefined :: ets:tab()
}).
-type nextFun() :: fun((#state{}) -> [syntaxTree()]).
-spec compile (Module::atom(), mod()) -> {ok, Module::atom()}.
compile(Module, ModuleData) ->
{ok, forms, Forms} = abstract_module(Module, ModuleData),
{ok, Module, Binary} = compile_forms(Forms, [nowarn_unused_vars]),
@ -67,6 +69,9 @@ abstract_module_(Module, #module{tables=Tables, qtree=Tree}=Data) ->
?erl:atom(handle),
?erl:integer(1))])]),
%% ]).
%% -spec info([
%% TODO
%% ]).
%% info(Name) -> Term.
?erl:function(
?erl:atom(info),
@ -74,13 +79,19 @@ abstract_module_(Module, #module{tables=Tables, qtree=Tree}=Data) ->
[?erl:clause(
[?erl:underscore()], none,
[abstract_apply(erlang, error, [?erl:atom(badarg)])])]),
%% table(Name) -> ets:tid().
%% -spec table([
%% TODO
%% ]).
%% table(Name) -> ets:tab().
?erl:function(
?erl:atom(table),
abstract_tables(Tables) ++
[?erl:clause(
[?erl:underscore()], none,
[abstract_apply(erlang, error, [?erl:atom(badarg)])])]),
%% -spec handle([
%% TODO
%% ]).
%% handle(Event) - entry function
?erl:function(
?erl:atom(handle),
@ -88,7 +99,10 @@ abstract_module_(Module, #module{tables=Tables, qtree=Tree}=Data) ->
[abstract_count(input),
?erl:application(none,
?erl:atom(handle_), [?erl:variable("Event")])])]),
%% input_(Node, App, Pid, Tags, Values) - filter roots
%% -spec handle_([
%% TODO
%% ]).
%% handle_(Node, App, Pid, Tags, Values) - filter roots
?erl:function(
?erl:atom(handle_),
[?erl:clause([?erl:variable("Event")], none,
@ -103,10 +117,14 @@ abstract_module_(Module, #module{tables=Tables, qtree=Tree}=Data) ->
AbstractMod.
%% @private Return the clauses of the table/1 function.
%-spec abstract_tables([{term(), atom()|binary()|maybe_improper_list()|number()|tuple()}]) ->
% ?erl:syntax_tree().
abstract_tables(Tables) ->
[?erl:clause(
[?erl:abstract(K)], none,
[?erl:abstract(V)])
% [?erl:tree(variable,V)])
% [?erl:variable("V")])
|| {K, V} <- Tables].
%% @private Return the clauses of the info/1 function.
@ -277,7 +295,7 @@ abstract_getparam_(Term, OnBound, #state{paramstab=Table,
] ++ OnBound(State#state{paramvars=[{Term, param_variable(Key)}|Params]}).
%% @private Generate a variable name for the value of a field.
-spec field_variable(atom()) -> string().
-spec field_variable(atom()) -> nonempty_string().
field_variable(Key) ->
"Field_" ++ field_variable_(atom_to_list(Key)).
@ -299,22 +317,10 @@ field_variable_([]) ->
param_variable(Key) ->
?erl:variable("Param_" ++ integer_to_list(Key)).
%% @private Generate a list of field variable names.
%% Walk the query tree and generate a safe variable name string for each field
%% that is accessed by the conditions in the query. Only allow alpha-numeric.
%%-spec field_variables(glc_ops:op()) -> [{atom(), string()}].
%%field_variables(Query) ->
%% lists:usort(field_variables_(Query)).
%%-spec field_variables(glc_ops:op()) -> [{atom(), string()}].
%%field_variables_({Key, '=', _Term}) ->
%% [{Key, field_variable(Key)}].
%% @private Return an expression to increment a counter.
%% @todo Pass state record. Only Generate code if `statistics' is enabled.
-spec abstract_count(atom()) -> syntaxTree().
-spec abstract_count(filter|input|output) -> syntaxTree().
abstract_count(Counter) ->
abstract_apply(ets, update_counter,
[abstract_apply(table, [?erl:atom(counters)]),
@ -324,7 +330,7 @@ abstract_count(Counter) ->
%% @private Return an expression to get the value of a counter.
%% @todo Pass state record. Only Generate code if `statistics' is enabled.
-spec abstract_getcount(atom()) -> [syntaxTree()].
-spec abstract_getcount(filter|input|output) -> [syntaxTree()].
abstract_getcount(Counter) ->
[abstract_apply(ets, lookup_element,
[abstract_apply(table, [?erl:atom(counters)]),
@ -356,11 +362,15 @@ load_binary(Module, Binary) ->
end.
%% @private Apply an exported function.
-spec abstract_apply(atom(), atom(), [syntaxTree()]) -> syntaxTree().
% underspec: -spec abstract_apply(atom(), atom(), [syntaxTree()]) -> syntaxTree().
-spec abstract_apply(erlang|ets|gre, '<'|'=:='|'>'|error|find|lookup_element|update_counter, [any(),...]) ->
syntaxTree().
abstract_apply(Module, Function, Arguments) ->
?erl:application(?erl:atom(Module), ?erl:atom(Function), Arguments).
%% @private Apply a module local function.
-spec abstract_apply(atom(), [syntaxTree()]) -> syntaxTree().
% underspec: -spec abstract_apply(atom(), [syntaxTree()]) -> syntaxTree().
-spec abstract_apply (table, [{tree, atom(), {_,_,_,_}, _}, ...]) ->
syntaxTree().
abstract_apply(Function, Arguments) ->
?erl:application(?erl:atom(Function), Arguments).

+ 2
- 0
src/glc_lib.erl View File

@ -87,6 +87,7 @@ repeat(Query, Fun) ->
%% @doc Return the output action of a query.
-spec onoutput ({_, '<'|'='|'>', _} | {_,'*'}) -> output.
onoutput({_, '<', _}) ->
output;
onoutput({_, '=', _}) ->
@ -99,6 +100,7 @@ onoutput(Query) ->
erlang:error(badarg, [Query]).
%% @doc Modify the output action of a query.
-spec onoutput (term(), term()) -> no_return().
onoutput(Action, Query) ->
erlang:error(badarg, [Action, Query]).

+ 25
- 17
src/glc_ops.erl View File

@ -19,40 +19,47 @@
union/1
]).
-type op_lt() :: {atom(), '<', term()}.
-type op_eq() :: {atom(), '=', term()}.
-type op_gt() :: {atom(), '>', term()}.
-type op_exists() :: {atom(), '*'}.
-type op_any() :: {any, [op(), ...]}.
-type op_all() :: {all, [op(), ...]}.
-type op_noop() :: {null, true|false}.
-type op() ::
{atom(), '<', term()} |
{atom(), '=', term()} |
{atom(), '>', term()} |
{atom(), '*'} |
{any, [op(), ...]} |
{all, [op(), ...]} |
{null, true|false}.
op_lt() |
op_eq() |
op_gt() |
op_exists() |
op_any() |
op_all() |
op_noop().
-export_type([op/0]).
%% @doc Test that a field value is less than a term.
-spec lt(atom(), term()) -> op().
-spec lt(Key::atom(), Term::term()) -> {n>Key::atompan>(), '<', Term::term()}.
lt(Key, Term) when is_atom(Key) ->
{Key, '<', Term};
lt(Key, Term) ->
erlang:error(badarg, [Key, Term]).
%% @doc Test that a field value is equal to a term.
-spec eq(atom(), term()) -> op().
-spec eq(Key::atom(), Term::term()) -> {n>Key::atompan>(), '=', Term::term()}.
eq(Key, Term) when is_atom(Key) ->
{Key, '=', Term};
eq(Key, Term) ->
erlang:error(badarg, [Key, Term]).
%% @doc Test that a field value is greater than a term.
-spec gt(atom(), term()) -> op().
-spec gt(Key::atom(), Term::term()) -> {n>Key::atompan>(), '>', Term::term()}.
gt(Key, Term) when is_atom(Key) ->
{Key, '>', Term};
gt(Key, Term) ->
erlang:error(badarg, [Key, Term]).
%% @doc Test that a field value is exists.
-spec wc(atom()) -> op().
%% @doc Test that a field value exists.
-spec wc(Key::atom()) -> {Key::atom(), '*'}.
wc(Key) when is_atom(Key) ->
{Key, '*'};
wc(Key) ->
@ -64,7 +71,7 @@ wc(Key) ->
%% in the list must hold for the input event. The list is expected to
%% be a non-empty list. If the list of filters is an empty list a `badarg'
%% error will be thrown.
-spec all([op()]) -> op().
-spec all(Conds :: [op(), ...]) -> {all, Conds :: [op(), ...]}.
all([_|_]=Conds) ->
{all, Conds};
all(Other) ->
@ -76,7 +83,7 @@ all(Other) ->
%% in the list must hold for the input event. The list is expected to be
%% a non-empty list. If the list of filters is an empty list a `badarg'
%% error will be thrown.
-spec any([op()]) -> op().
-spec any(Conds :: [op(), ...]) -> {any, Conds :: [op(), ...]}.
any([_|_]=Conds) ->
{any, Conds};
any(Other) ->
@ -84,7 +91,7 @@ any(Other) ->
%% @doc Always return `true' or `false'.
-spec null(boolean()) -> op().
-spec null(Result::boolean()) -> {null, Result::boolean()}.
null(Result) when is_boolean(Result) ->
{null, Result};
null(Result) ->
@ -95,7 +102,8 @@ null(Result) ->
%% Updating the output action of a query finalizes it. Attempting
%% to use a finalized query to construct a new query will result
%% in a `badarg' error.
-spec with(op(), fun((gre:event()) -> term())) -> op().
-spec with(Query::op(), Fun::fun((gre:event()) -> term())) ->
{with, Query::op(), Fun::fun((gre:event()) -> term())}.
with(Query, Fun) when is_function(Fun, 1) ->
{with, Query, Fun};
with(Query, Fun) ->
@ -111,7 +119,7 @@ with(Query, Fun) ->
%% All queries are expected to be valid and have an output action other
%% than the default which is `output'. If these expectations don't hold
%% a `badarg' error will be thrown.
-spec union([op()]) -> op().
-spec union(Queries::[op()]) -> {union, Queries::[op()]}.
union(Queries) ->
case [Query || Query <- Queries, glc_lib:onoutput(Query) =:= output] of
[] -> {union, Queries};

+ 1
- 1
src/gre.erl View File

@ -25,7 +25,7 @@
]).
-type event() :: {list, [{atom(), term()}]}.
-export_types([event/0]).
-export_type([event/0]).
%% @doc Construct an event term.
-spec make(term(), [list]) -> event().

Loading…
Cancel
Save