]> mj.ucw.cz Git - leo.git/blob - expr.i
Initial support for LUA bindings in stylesheets
[leo.git] / expr.i
1 /*
2  *      Hic Est Leo -- Bindings for Lua
3  *
4  *      (c) 2015 Martin Mares <mj@ucw.cz>
5  */
6
7 %module leo
8 %nodefaultctor;
9
10 %{
11 #include "leo.h"
12 #include "osm.h"
13 #include "css.h"
14 #include "expr.h"
15
16 #include <lualib.h>
17 #include <lauxlib.h>
18 %}
19
20 /*** Proxy for OSM object attributes ***/
21
22 %{
23
24 struct proxy_tag {
25   struct osm_object *o;
26 };
27
28 static void push_proxy_tag(lua_State *L, struct proxy_tag *t)
29 {
30   SWIG_NewPointerObj(L, t, SWIGTYPE_p_proxy_tag, 0);
31 }
32
33 static const char *proxy_tag_index(struct proxy_tag *t, const char *key)
34 {
35   osm_key_t k = osm_key_encode(key);
36   osm_val_t v = osm_obj_find_tag(t->o, k);
37   return osm_val_decode(v);
38 }
39
40 %}
41
42 struct proxy_tag { };
43
44 %extend proxy_tag {
45   const char *index(const char *key);
46 };
47
48 %init %{
49   // This overrides default index function generated by SWIG.
50   // The tag proxy therefore cannot have any methods.
51   SWIG_Lua_get_class_metatable(L, "proxy_tag");
52   SWIG_Lua_add_function(L, "__index", _wrap_proxy_tag_index);
53   lua_pop(L, 1);
54 %}
55
56 /*** Proxy for style properties ***/
57
58 %{
59
60 struct proxy_style {
61   struct style_results *sr;
62   layer_t layer;
63 };
64
65 static void push_proxy_style(lua_State *L, struct proxy_style *s)
66 {
67   SWIG_NewPointerObj(L, s, SWIGTYPE_p_proxy_style, 0);
68 }
69
70 static const char *proxy_style_index(struct proxy_style *s, const char *key)
71 {
72   return NULL;
73 }
74
75 %}
76
77 struct proxy_style { };
78
79 %extend proxy_style {
80   const char *index(const char *key);
81 };
82
83 %init %{
84   // This overrides default index function generated by SWIG.
85   SWIG_Lua_get_class_metatable(L, "proxy_style");
86   SWIG_Lua_add_function(L, "__index", _wrap_proxy_style_index);
87   lua_pop(L, 1);
88 %}
89
90 /*** Compilation and running of expressions ***/
91
92 %{
93
94 static lua_State *lua;
95
96 void expr_init(void)
97 {
98   lua = luaL_newstate();
99   lua_State *L = lua;
100
101   luaL_openlibs(L);
102   luaopen_leo(L);
103
104   // SWIG init code leaves data in Lua stack. Get rid of it.
105   lua_pop(L, lua_gettop(L));
106
107   lua_checkstack(L, 30);
108
109   lua_pushliteral(L, "Leo");
110   lua_newtable(L);
111   lua_settable(L, LUA_REGISTRYINDEX);
112 }
113
114 #if 0
115 // Not used at the moment (FIXME)
116
117 static char *current_src;
118
119 static const char *expr_reader(lua_State *L UNUSED, void *data UNUSED, size_t *sizep)
120 {
121   if (current_src)
122     {
123       char *res = current_src;
124       *sizep = strlen(res);
125       current_src = NULL;
126       return res;
127     }
128   else
129     {
130       *sizep = 0;
131       return NULL;
132     }
133 }
134
135 #endif
136
137 void expr_compile(void *key, char *source)
138 {
139   lua_State *L = lua;
140
141   lua_pushliteral(L, "Leo");                    // stack: "Leo"
142   lua_gettable(L, LUA_REGISTRYINDEX);           // stack: leo-table
143   ASSERT(lua_istable(L, -1));
144   lua_pushlightuserdata(L, key);                // stack: leo-table, key
145
146 #if 0
147   current_src = source;
148   int err = lua_load(L, expr_reader, NULL, "@(expr)", NULL);
149 #else
150   int err = luaL_loadbuffer(L, source, strlen(source), "@expression");
151 #endif
152   if (err != LUA_OK)
153     css_error(lua_tostring(L, -1));
154   // stack: leo-table, key, function
155
156   lua_settable(L, -3);                          // stack: leo-table
157   lua_pop(L, 1);                                // stack: --
158 }
159
160 void expr_execute(void *key, struct style_results *r, layer_t layer)
161 {
162   lua_State *L = lua;
163
164   struct proxy_tag pt = { .o = r->obj };
165   push_proxy_tag(L, &pt);                       // stack: proxy
166   lua_setglobal(L, "t");                        // stack: --
167
168   struct proxy_style ps = { .sr = r, .layer = layer };
169   push_proxy_style(L, &ps);                     // stack: proxy
170   lua_setglobal(L, "s");                        // stack: --
171
172   lua_pushliteral(L, "Leo");                    // stack: "Leo"
173   lua_gettable(L, LUA_REGISTRYINDEX);           // stack: leo-table
174   ASSERT(lua_istable(L, -1));
175   lua_pushlightuserdata(L, key);                // stack: leo-table, key
176   lua_gettable(L, -2);                          // stack: leo-table, function
177   lua_remove(L, -2);                            // stack: function
178   ASSERT(lua_isfunction(L, -1));
179
180   lua_call(L, 0, 0);                            // stack: --
181 }
182
183 %}