/Lua/src/apl-lua.cpp

http://luapl.googlecode.com/ · C++ · 1406 lines · 1213 code · 113 blank · 80 comment · 212 complexity · 0769421ea2492c6cf6b88275c886d45e MD5 · raw file

  1. //#include "stdafx.h"
  2. #include <assert.h>
  3. #include <string>
  4. #include <string.h>
  5. #include <sstream>
  6. #include <vector>
  7. //#include <dirent.h>
  8. #include <errno.h>
  9. #include <a/k.h>
  10. #include <a/f.h>
  11. #include <a/fncdcls.h>
  12. //#include "Aplus.h"
  13. extern "C" {
  14. #include "lua.h"
  15. #include "lauxlib.h"
  16. #include "lualib.h"
  17. }
  18. using namespace std;
  19. //////////////////////////////////////////////////////////////////////////////
  20. // Forward function declarations
  21. //////////////////////////////////////////////////////////////////////////////
  22. extern "C" void checkmem();
  23. class Tok;
  24. static A doeval(lua_State *L,E e,bool retdata);
  25. static A getAObject(lua_State *L, const Tok& atok, bool reverseOrder = true);
  26. static A doassign(lua_State *L, E e);
  27. static A table2aobject(lua_State *L, int args);
  28. extern "C" A ep_alsf(A a);
  29. extern "C" A ep_flat(A a);
  30. extern "C" I ep_issf(A a);
  31. extern "C" A ep_imp(A a);
  32. extern "C" A ep_exp(A a);
  33. extern "C" A ep_ssr(A s, A t, A r);
  34. extern "C" A ep_ss(A s, A t);
  35. extern A aplus_nl;
  36. //////////////////////////////////////////////////////////////////////////////
  37. // A+ operator definitions
  38. //////////////////////////////////////////////////////////////////////////////
  39. const int op_assign = 0x04;
  40. const int op_brackets = 0x07;
  41. const int op_count = 0xA6;
  42. const int op_each = 0x4C;
  43. const int op_plus = 0x16;
  44. const int op_match = 0xEE;
  45. const int op_minus = 0x36;
  46. const int op_multiply = 0x1E;
  47. const int op_rank = 0x44;
  48. const int op_divide = 0x3E;
  49. const int op_strand = 0x3C;
  50. const int op_pow = 0x7E;
  51. const int op_umn = 0x36;
  52. const int op_le = 0x6E;
  53. const int op_lt = 0x4E;
  54. struct APL_OPERATOR {
  55. const char* name;
  56. unsigned int code;
  57. } APL_OPTABLE[] = {
  58. { "assigninto", 0x04 },
  59. { "_in", 0x116 },
  60. { "_and", 0x06 },
  61. { "_or", 0x0E },
  62. { "_not", 0xBE },
  63. { "_type", 0x0E },
  64. { "_unpack", 0xFE },
  65. { "abs", 0x46 },
  66. { "bag", 0x11E },
  67. { "bins", 0xDE },
  68. { "choose", 0xA6 },
  69. { "compress", 0x106 },
  70. { "concat", 0xB6 },
  71. { "count", 0xA6 },
  72. { "decode", 0xF6 },
  73. { "depth", 0xEE },
  74. { "disclose", 0x56 },
  75. { "div", 0x3E },
  76. { "drop", 0xD6 },
  77. { "each", 0x4C },
  78. { "enclose", 0x4E },
  79. { "equals", 0x5E },
  80. { "exp", 0x7E },
  81. { "find", 0x9E },
  82. { "gradeup", 0xDE },
  83. { "gradedown", 0xE6 },
  84. { "gt", 0x56 },
  85. { "gte", 0x76 },
  86. { "inner", 0x216 },
  87. { "innermax", 0x226 },
  88. { "innermin", 0x22E },
  89. { "laminate", 0xBE },
  90. { "lt", 0x4E },
  91. { "lte", 0x6E },
  92. { "log", 0x86 },
  93. { "match", 0xEE },
  94. { "mod", 0x46 },
  95. { "minus", 0x36 },
  96. { "mult", 0x1E },
  97. { "neg", 0x36 },
  98. { "outermult", 0x1ae },
  99. { "outerplus", 0x1a6 },
  100. { "outerdiv", 0x1ce },
  101. { "outerminus", 0x1c6 },
  102. { "outerequals", 0x1ee },
  103. { "outergte", 0x206 },
  104. { "outergt", 0x1e6 },
  105. { "outerlt", 0x1de },
  106. { "outerlte", 0x1fe },
  107. { "outermax", 0x1b6 },
  108. { "outermin", 0x1be},
  109. { "pack", 0xF6 },
  110. { "pi", 0x13E },
  111. { "plus", 0x16 },
  112. { "pick", 0x126 },
  113. { "pow", 0x7E },
  114. { "rake", 0x116 },
  115. { "rand", 0x8E },
  116. { "rank", 0x44 },
  117. { "ravel", 0xB6 },
  118. { "raze" , 0x126 },
  119. { "replicate", 0x106 },
  120. { "restructure", 0x136 },
  121. { "right", 0x24E },
  122. { "reverse", 0xC6 },
  123. { "rot", 0xC6 },
  124. { "shape", 0xAE},
  125. { "solve", 0x12E },
  126. { "sum", 0x186 },
  127. { "take", 0xCE },
  128. { "til", 0x9E },
  129. { "iota", 0x9E },
  130. { "transpose", 0x96 },
  131. { NULL, 0 }
  132. };
  133. static void registerOperator(lua_State *L,APL_OPERATOR* op) {
  134. lua_pushlightuserdata(L, (void*)op->code);
  135. lua_setglobal(L, op->name);
  136. }
  137. //////////////////////////////////////////////////////////////////////////////
  138. // Lua function call parsing
  139. //////////////////////////////////////////////////////////////////////////////
  140. enum ETokType {
  141. NotSet, Invalid, Null, Int, Float, Char, Operator, Function, AObject
  142. };
  143. class Tok
  144. {
  145. public:
  146. Tok();
  147. void Append(A aobj);
  148. void Append(lua_State *L, int args);
  149. bool CanAppend(int luatype);
  150. int Length() const;
  151. public:
  152. int iNumArgs;
  153. ETokType iType;
  154. long iOperator;
  155. vector<double> iNum;
  156. vector<string> iStr;
  157. vector<A> iA;
  158. };
  159. Tok::Tok() {
  160. // Constructor
  161. iNumArgs = 0;
  162. iOperator = 0;
  163. iType = NotSet;
  164. }
  165. int Tok::Length() const {
  166. // Return the number of AObjects held by the tok
  167. switch(iType) {
  168. case NotSet: return 0;
  169. case Invalid: return 0;
  170. case Null: return 0;
  171. case Int: return 1;
  172. case Float: return 1;
  173. case Char: return iStr.size();
  174. case Operator: return 1;
  175. case Function: return 1;
  176. case AObject: return iA.size();
  177. default:
  178. break;
  179. }
  180. return 0;
  181. }
  182. void Tok::Append(A aobj) {
  183. // Append an aobj
  184. assert((iType == AObject) || (iType == NotSet));
  185. if (iType==NotSet) iType = AObject;
  186. iA.push_back(aobj);
  187. }
  188. void Tok::Append(lua_State *L, int args) {
  189. // First arg of a new token - initialize type
  190. iNumArgs++;
  191. int luatype = lua_type(L,args);
  192. switch(luatype) {
  193. case LUA_TNIL:
  194. iType = Null;
  195. break;
  196. case LUA_TNUMBER: {
  197. if (iType==NotSet) iType = Int;
  198. double val = luaL_checknumber(L, args);
  199. iNum.push_back(val);
  200. if (fabs(double(int(val))-val)>CT) {
  201. iType = Float;
  202. }
  203. break;
  204. }
  205. case LUA_TBOOLEAN: {
  206. if (iType==NotSet) iType = Int;
  207. double val = lua_toboolean(L, args);
  208. iNum.push_back(val);
  209. break;
  210. }
  211. case LUA_TSTRING: {
  212. iType = Char;
  213. string val = lua_tostring(L, args);
  214. iStr.push_back(val);
  215. break;
  216. }
  217. break;
  218. case LUA_TTABLE: {
  219. iType = AObject;
  220. A a = table2aobject(L,args);
  221. iA.push_back(a);
  222. break;
  223. }
  224. case LUA_TFUNCTION: {
  225. iType = Function;
  226. lua_pushvalue(L, args);
  227. iOperator = luaL_ref(L, LUA_REGISTRYINDEX);
  228. break;
  229. }
  230. case LUA_TUSERDATA: {
  231. iType = AObject;
  232. void * ud = luaL_checkudata(L,args,"APLOBJ");
  233. iA.push_back(*(A*)ud);
  234. break;
  235. }
  236. case LUA_TTHREAD: {
  237. iType = Invalid;
  238. break;
  239. }
  240. case LUA_TLIGHTUSERDATA: {
  241. iType = Operator;
  242. void* ud = lua_touserdata(L,args);
  243. iOperator = reinterpret_cast<long>(ud);
  244. break;
  245. }
  246. };
  247. }
  248. bool Tok::CanAppend(int luatype) {
  249. // Return true if we can append arg to the token
  250. if (iType==NotSet) return true;
  251. if (iType==Int) return (luatype==LUA_TNUMBER || luatype==LUA_TBOOLEAN);
  252. if (iType==Float) return (luatype==LUA_TNUMBER || luatype==LUA_TBOOLEAN);
  253. if (iType==AObject) return (luatype==LUA_TUSERDATA);
  254. return false;
  255. }
  256. enum TokArgs { NoGrouping, NoAObjGrouping, Grouping };
  257. static bool tokgrouping(const Tok& tok, TokArgs dogrouping) {
  258. // Return true if the tok can be grouped
  259. if (dogrouping==Grouping) return true;
  260. if (dogrouping==NoGrouping) return false;
  261. if (dogrouping==NoAObjGrouping && tok.iType==AObject) return false;
  262. return true;
  263. }
  264. static A table2slotfiller(lua_State *L) {
  265. // Loop over table and create slotfiller
  266. vector<string> syms;
  267. vector<A> objs;
  268. int count = 0;
  269. lua_pushnil(L);
  270. while(lua_next(L, -2)) {
  271. if(lua_isstring(L,-2)) {
  272. string key = lua_tostring(L, -2);
  273. syms.push_back(key);
  274. } else {
  275. std::stringstream result;
  276. result << count;
  277. syms.push_back(result.str());
  278. }
  279. Tok arg;
  280. arg.Append(L,-1);
  281. A a = getAObject(L,arg);
  282. objs.push_back(a);
  283. count++;
  284. lua_pop(L, 1);
  285. }
  286. A sf = gv(Et,2);
  287. int size = syms.size();
  288. A sym = gv(Et,size);
  289. for(int i=0;i<size;i++) {
  290. sym->p[i]=MS(si(syms[i].c_str()));
  291. }
  292. A obj = gv(Et,size);
  293. for(int i=0;i<size;i++) {
  294. obj->p[i]=(I)objs[i];
  295. }
  296. sf->p[0] = (I)sym;
  297. sf->p[1] = (I)obj;
  298. return sf;
  299. }
  300. static A table2array(lua_State *L) {
  301. vector<A> objs;
  302. Tok tok;
  303. lua_pushnil(L);
  304. while(lua_next(L, -2)) {
  305. int argtype = lua_type(L,-1);
  306. if (tok.iType==NotSet || (tokgrouping(tok,Grouping) && tok.CanAppend(argtype))) {
  307. tok.Append(L,-1);
  308. } else {
  309. A a = getAObject(L,tok,false);
  310. objs.push_back(a);
  311. tok = Tok();
  312. tok.Append(L,-1);
  313. }
  314. lua_pop(L, 1);
  315. }
  316. A a = getAObject(L,tok,false);
  317. objs.push_back(a);
  318. int size = (int)objs.size();
  319. if (size==1) return a;
  320. a = gv(Et,size);
  321. for(int i=0;i<size;i++) { ((I*)(a->p))[i]=(I)objs[i]; }
  322. return a;
  323. }
  324. static A table2aobject(lua_State *L, int args) {
  325. // Loop over table key/value pairs
  326. // If first key == string -> create slotfiller
  327. // else create nested aobject
  328. lua_pushvalue(L,args);
  329. lua_pushnil(L);
  330. lua_next(L, -2);
  331. int keytype = lua_type(L,-2);
  332. lua_pop(L,2); // reset stack;
  333. A a = NULL;
  334. if(keytype==LUA_TSTRING) {
  335. a = table2slotfiller(L);
  336. } else {
  337. a = table2array(L);
  338. }
  339. lua_pop(L,1);
  340. return a;
  341. }
  342. static void tokenizeArgs(lua_State *L, vector<Tok>& toks, TokArgs dogrouping=Grouping) {
  343. // Loop through the arguments passed from Lua and create a vector of toks
  344. // eg: group args 1,2,3 into a single A+ int vector.
  345. int argsInit=lua_gettop(L);
  346. int args = argsInit;
  347. Tok tok;
  348. while(args>0) {
  349. int argtype = lua_type(L,args);
  350. if (tok.iType==NotSet || (tokgrouping(tok,dogrouping) && tok.CanAppend(argtype))) {
  351. tok.Append(L,args);
  352. } else {
  353. toks.push_back(tok);
  354. tok = Tok();
  355. tok.Append(L,args);
  356. }
  357. args--;
  358. }
  359. toks.push_back(tok);
  360. int argsFinal=lua_gettop(L);
  361. lua_pop(L, argsInit);
  362. }
  363. //////////////////////////////////////////////////////////////////////////////
  364. // Lua function call
  365. //////////////////////////////////////////////////////////////////////////////
  366. extern "C" I *Y;
  367. extern C* qs;
  368. extern "C"
  369. I luaplCallLua(A fnc, I numargs) {
  370. lua_State *L = (lua_State*)(fnc->i);
  371. int stacksize=lua_gettop(L);
  372. long fnref = fnc->d[0];
  373. lua_rawgeti(L, LUA_REGISTRYINDEX, fnref); /* push stored function */
  374. stacksize=lua_gettop(L);
  375. A* luaarg = (A*) lua_newuserdata(L, sizeof(A));
  376. luaL_getmetatable(L, "APLOBJ");
  377. lua_setmetatable(L, -2);
  378. (*luaarg) = (A)ic((A)Y[1]);
  379. if(numargs>1) {
  380. A* luaarg2 = (A*) lua_newuserdata(L, sizeof(A));
  381. luaL_getmetatable(L, "APLOBJ");
  382. lua_setmetatable(L, -2);
  383. (*luaarg2) = (A)ic((A)Y[2]);
  384. }
  385. int numresults = 1;
  386. stacksize=lua_gettop(L);
  387. int retcode = lua_pcall(L, numargs, numresults, 0);
  388. stacksize=lua_gettop(L);
  389. // luaL_unref(L, LUA_REGISTRYINDEX, fnref);
  390. A res = 0;
  391. if(retcode!=0) {
  392. q = 15; qs = (char*) lua_tostring(L, -1);
  393. } else {
  394. Tok tok;
  395. tok.Append(L,-1);
  396. stacksize=lua_gettop(L);
  397. A ret = getAObject(L,tok);
  398. stacksize=lua_gettop(L);
  399. if (QV(ret)) {
  400. V v = XV(ret);
  401. res = (A)ic((A)(v->a));
  402. } else {
  403. res = ret;
  404. }
  405. lua_pop(L, 1);
  406. }
  407. return (I)res;
  408. }
  409. //////////////////////////////////////////////////////////////////////////////
  410. // A(...) function parameter parsing
  411. //////////////////////////////////////////////////////////////////////////////
  412. static E newExpr(long fncode, int argCount, long a0, long a1)
  413. // Return an expression structure
  414. {
  415. E e=(E)(ma(2+argCount)); // 2+numArgs
  416. e->n=argCount;
  417. e->f=fncode;
  418. switch(argCount){
  419. case 0:break;
  420. case 1:e->a[0]=a0;break;
  421. default:e->a[0]=a0,e->a[1]=a1;break;
  422. }
  423. return e;
  424. }
  425. static A getStrand(lua_State *L, const Tok& atok, bool reverseOrder = true) {
  426. // Convert a tok into a tuple of A objects
  427. int args = atok.Length();
  428. E e=(E)(ma(2+args)); // 2+numArgs
  429. e->n=args;
  430. e->f=op_strand; // xli function id
  431. for(int i=0;i<args;i++) {
  432. Tok tmp;
  433. tmp.iType = atok.iType;
  434. if (tmp.iType==Char) tmp.iStr.push_back(atok.iStr[i]);
  435. if (tmp.iType==AObject) tmp.iA.push_back(atok.iA[i]);
  436. A arg = getAObject(L,tmp);
  437. e->a[reverseOrder ? args-i-1 : i]=(I)arg;
  438. }
  439. A res = doeval(L,(E)e,true);
  440. return res;
  441. }
  442. static A getAObject(lua_State *L, const Tok& atok, bool reverseOrder) {
  443. // Convert a Tok into an A object
  444. checkmem();
  445. if (atok.Length()>1 && (atok.iType==Char || atok.iType==AObject))
  446. return getStrand(L,atok);
  447. A a = NULL;
  448. switch(atok.iType) {
  449. case Null: {
  450. a = aplus_nl;
  451. break;
  452. }
  453. case Int: {
  454. unsigned int size = atok.iNum.size();
  455. if (size==1) {
  456. a = gi((I)atok.iNum[0]);
  457. } else {
  458. a = gv(It,size);
  459. for(unsigned int i=0;i<size;i++) { ((I*)(a->p))[(reverseOrder) ? size-i-1 : i]=(I)atok.iNum[i]; }
  460. }
  461. break;
  462. }
  463. case Float: {
  464. unsigned int size = atok.iNum.size();
  465. if (size==1) {
  466. a = gf(atok.iNum[0]);
  467. } else {
  468. a = gv(Ft,size);
  469. for(unsigned int i=0;i<size;i++) { ((F*)(a->p))[(reverseOrder) ? size-i-1 : i]=(F)atok.iNum[i]; }
  470. }
  471. break;
  472. }
  473. case Char: {
  474. assert(atok.iStr.size()==1);
  475. unsigned int size = atok.iStr[0].size();
  476. if (size==1) {
  477. a = gi(atok.iStr[0][0]);
  478. a->t = Ct;
  479. } else {
  480. a = gv(Ct,size);
  481. for(unsigned int i=0;i<size;i++) { ((C*)(a->p))[i]=(C)atok.iStr[0][i]; }
  482. }
  483. break;
  484. }
  485. case Operator:
  486. a = (A)atok.iOperator;
  487. break;
  488. case AObject: {
  489. assert(atok.iA.size()==1);
  490. a = (A)ic(atok.iA[0]);
  491. break;
  492. }
  493. case Function:
  494. case NotSet:
  495. case Invalid:
  496. default:
  497. assert(0); // should never reach here
  498. break;
  499. }
  500. checkmem();
  501. return a;
  502. }
  503. Tok parseGetArg(lua_State *L, int& index, const vector<Tok>& toks) {
  504. // Return an AObject or NULL
  505. Tok empty;
  506. if (index>=(int)toks.size()) return empty;
  507. Tok arg = toks[index];
  508. Tok next;
  509. if (index+1<(int)toks.size()) next = toks[index+1];
  510. if ((arg.iType == Operator) || (arg.iType == Function)) return empty;
  511. if (next.iOperator==op_rank) return empty;
  512. index++;
  513. return arg;
  514. }
  515. A parseGetAObj(lua_State *L, int& index, const vector<Tok>& toks) {
  516. // Return an AObject or NULL
  517. if (index>=(int)toks.size()) return NULL;
  518. Tok arg(parseGetArg(L,index,toks));
  519. if (arg.iType==NotSet) return NULL;
  520. A a = getAObject(L,arg);
  521. return a;
  522. }
  523. /*A evaleachfn(lua_State *L,long opcode) {
  524. // Evaluate opcode with each to create an executable A+ object
  525. E e = newExpr(op_each,1,opcode,0);
  526. A d = doeval(L,e,true);
  527. return d;
  528. }*/
  529. A evalrankfn(lua_State *L, Tok arg, long opcode) {
  530. // Evaluate opcode with each to create an executable A+ object
  531. A a = getAObject(L,arg);
  532. E e = newExpr(op_rank,2,opcode,(I)a);
  533. A d = doeval(L,e,true);
  534. return d;
  535. }
  536. static long getFunction(lua_State *L, const Tok& atok, int numargs) {
  537. // Convert a tok into a function or operator code
  538. A a = gv(It,3);
  539. a->t = 9;
  540. a->n = 1;
  541. a->r = 2;
  542. if (numargs>1) a->r = 3;
  543. (a->d[0]) = atok.iOperator; (a->d[1]) = 0; (a->d[2]) = 0;
  544. (a->i) = (I)L; (a->p[0]) = (I)gv(Ct,4); // dummy function name
  545. (a->p[1]) = 0; (a->p[2]) = 0;
  546. return (I)a;
  547. }
  548. Tok parseGetOp(lua_State *L, int& index, const vector<Tok>& toks) {
  549. // Return an operator or uninitialized token
  550. Tok arg;
  551. if (index>=(int)toks.size()) return arg;
  552. arg = toks[index];
  553. if ((arg.iType == Operator) || (arg.iType == Function)) {
  554. index++;
  555. if (arg.iType == Operator && arg.iOperator==op_each) {
  556. Tok fn = parseGetOp(L,index,toks);
  557. if (fn.iType==NotSet) luaL_error(L,"luAPL error: Parse - each must operate on a function");
  558. if (fn.iType==Function) {
  559. int peek = index;
  560. Tok nextarg = parseGetArg(L,peek,toks);
  561. int numargs = (nextarg.iType==NotSet) ? 1 : 2;
  562. fn.iOperator = getFunction(L,fn,numargs);
  563. }
  564. // arg.iOperator = (I)evaleachfn(L,fn.iOperator);
  565. A z = gv(Xt,0);
  566. z->r = 2;
  567. z->d[0] = op_each;
  568. z->d[1] = fn.iOperator;
  569. arg.iOperator = (I)z;
  570. }
  571. return arg;
  572. }
  573. Tok next;
  574. if (index+2>=(int)toks.size()) return next;
  575. if (toks[index+1].iOperator!=op_rank) return next;
  576. Tok fn = toks[index+2];
  577. if ((fn.iType != Operator) && (fn.iType != Function)) return next;
  578. if (fn.iType==Function) {
  579. int peek = index+3;
  580. Tok nextarg = parseGetArg(L,peek,toks);
  581. int numargs = (nextarg.iType==NotSet) ? 1 : 2;
  582. fn.iOperator = getFunction(L,fn,numargs);
  583. }
  584. index+=3;
  585. fn.iType = Operator;
  586. fn.iOperator = (I)evalrankfn(L,arg,fn.iOperator);
  587. return fn;
  588. }
  589. static E parsetoks(lua_State *L, int& index, const vector<Tok>& toks, E e) {
  590. // Create an expr from the incoming toks
  591. if (e==NULL) {
  592. A arg1 = parseGetAObj(L,index,toks);
  593. if (arg1==NULL) {
  594. luaL_error(L,"luAPL error: Parse - expected value as first token");
  595. }
  596. Tok op = parseGetOp(L,index,toks);
  597. if (op.iType==NotSet) return (E)arg1;
  598. A arg2 = parseGetAObj(L,index,toks);
  599. if (arg2==NULL) { arg2=arg1; arg1=NULL; }
  600. if (op.iType==Operator && op.iOperator==op_assign) { A tmp=arg2; arg2=arg1; arg1=tmp; }
  601. if (op.iType==Function) { op.iOperator = getFunction(L,op,(arg1)?2:1); }
  602. E expr = newExpr(op.iOperator,(arg1)?2:1,(I)arg2,(I)arg1);
  603. return (E)ME(expr);
  604. }
  605. Tok op = parseGetOp(L,index,toks);
  606. if (op.iType==NotSet) luaL_error(L,"luAPL error: Parse - expected operator or function");
  607. A arg1 = parseGetAObj(L,index,toks);
  608. if (arg1==NULL) { arg1=(A)e; e=NULL; }
  609. if (op.iOperator==op_assign) { I tmp=(I)e; e=(E)arg1; arg1=(A)tmp; }
  610. if (op.iType==Function) { op.iOperator = getFunction(L,op,(e)?2:1); }
  611. E expr = newExpr(op.iOperator,(e)?2:1,(I)arg1,(I)e);
  612. return (E)ME(expr);
  613. }
  614. static E parseargs(lua_State *L) {
  615. // Parse incoming arguments into an E
  616. vector<Tok> toks;
  617. tokenizeArgs(L,toks);
  618. E e = NULL;
  619. int i=0;
  620. while(i<(int)toks.size()) {
  621. e = parsetoks(L,i,toks,e);
  622. }
  623. return e;
  624. }
  625. static A doeval(lua_State *L,E e,bool retdata=true) {
  626. // Evaluate an A+ expression under a protective "do"
  627. // Recursively frees the expr structure e
  628. checkmem();
  629. E e0=(E)(ma(3));
  630. e0->n=1;
  631. e0->f=(I)aplus_pi((char *)"do");
  632. e0->a[0]=ME(e);
  633. A result=(A)ez(ME(e0));
  634. A rc=(A)result->p[0];
  635. A data=(A)result->p[1];
  636. checkmem();
  637. ef(ME(e0));
  638. checkmem();
  639. if ( 0 == rc->p[0] )
  640. {
  641. if(retdata) ic(data);
  642. dc(result);
  643. if(retdata) return data;
  644. return 0;
  645. }
  646. string errname((qs)? qs : (char*)(data->p));
  647. int errcode = *(int*)rc->p;
  648. dc(result);
  649. luaL_error(L,"luAPL error %d: %s",errcode, errname.c_str());
  650. return 0;
  651. }
  652. static A doassign(lua_State *L, E e) {
  653. // Evaluate an A+ expression and assign the result to a new variable
  654. E e1=(E)(ma(4));
  655. e1->n=2;
  656. e1->f=op_assign;
  657. V v=(V)malloc(sizeof(struct _v));memset(v,0,sizeof(struct _v));
  658. e1->a[0]=MV(v);
  659. e1->a[1]=ME(e);
  660. doeval(L,e1,false);
  661. return (A)MV(v);
  662. }
  663. static int assigninto(lua_State *L) {
  664. // Update the value of a variable
  665. E e = parseargs(L);
  666. doeval(L,(E)e,false);
  667. return 0;
  668. }
  669. int assign(lua_State *L) {
  670. // Evaluate an expression and assign the result to a variable
  671. E e = parseargs(L);
  672. A res = NULL;
  673. if (QE(e)) {
  674. res = doassign(L,e);
  675. } else if (QV(e)) {
  676. V v=(V)malloc(sizeof(struct _v));memset(v,0,sizeof(struct _v));
  677. v->a = ic((A)XV(e)->a);
  678. res = (A)MV(v);
  679. } else {
  680. V v=(V)malloc(sizeof(struct _v));memset(v,0,sizeof(struct _v));
  681. v->a = (I)e;
  682. res = (A)MV(v);
  683. }
  684. A* luares = (A*) lua_newuserdata(L, sizeof(A));
  685. luaL_getmetatable(L, "APLOBJ");
  686. lua_setmetatable(L, -2);
  687. (*luares) = res;
  688. return 1;
  689. }
  690. static A getA(lua_State *L) {
  691. // Pull an A+ object off the lua stack
  692. A a = *(A*)luaL_checkudata(L, 1, "APLOBJ");
  693. if(QV(a)) a = (A)XV(a)->a;
  694. return a;
  695. }
  696. static int debug(lua_State *L) {
  697. // Hit a breakpoint in the debugger
  698. return 0;
  699. }
  700. static int sqrBrackets(lua_State *L) {
  701. // Evaluate x[...] and return a value
  702. vector<Tok> toks;
  703. tokenizeArgs(L,toks,NoAObjGrouping);
  704. A a = getAObject(L,toks[0]); if(QV(a)) a = (A)ic((A)XV(a)->a);
  705. A x = getAObject(L,toks[1]);
  706. int n=2;
  707. if (a->t==Et) n = 1+a->n;
  708. E e1=newExpr(op_brackets,n,(I)x,(I)a);
  709. if (a->t==Et) {
  710. for(int i=0;i<a->n;i++) {
  711. ((I*)(e1->a))[i+1] = ic((A)(a->p)[i]);
  712. }
  713. dc(a);
  714. }
  715. A res = doeval(L,e1);
  716. A* luares = (A*) lua_newuserdata(L, sizeof(A));
  717. luaL_getmetatable(L, "APLOBJ");
  718. lua_setmetatable(L, -2);
  719. (*luares) = res;
  720. return 1;
  721. }
  722. static int assign2SqrBrackets(lua_State *L) {
  723. // Evaluate x[...] and return a value
  724. vector<Tok> toks;
  725. tokenizeArgs(L,toks,NoGrouping);
  726. A a = getAObject(L,toks[1]);
  727. A x = getAObject(L,toks[2]);
  728. A v = getAObject(L,toks[0]);
  729. E e1=newExpr(op_brackets,2,(I)x,(I)a);
  730. E e2=newExpr(op_assign,2,ME(e1),(I)v);
  731. A res = doeval(L,e2);
  732. A* luares = (A*) lua_newuserdata(L, sizeof(A));
  733. luaL_getmetatable(L, "APLOBJ");
  734. lua_setmetatable(L, -2);
  735. (*luares) = res;
  736. return 1;
  737. }
  738. namespace AFn {
  739. // forward declarations
  740. static bool pushValue(lua_State *L, A a);
  741. static int type2str(lua_State *L) {
  742. // Return the type of the A object
  743. A a = getA(L);
  744. const char* typestr = NULL;
  745. switch(a->t) {
  746. case It: typestr = "INT"; break;
  747. case Ft: typestr = "FLOAT"; break;
  748. case Ct: typestr = "CHAR"; break;
  749. case Et: typestr = sym(a)?"SYMBOL":"NESTED"; break;
  750. case Xt: typestr = "FUNCTION"; break;
  751. default: typestr = "UNKNOWN"; break;
  752. }
  753. lua_pushstring(L,typestr);
  754. return 1;
  755. }
  756. static bool pushNumberRecursive(lua_State *L, int rank, int& index, A a) {
  757. if (rank<=1) {
  758. if (index>=a->n) return false;
  759. if (a->t==It) {
  760. lua_pushinteger(L,((I*)a->p)[index]);
  761. } else {
  762. lua_pushnumber(L,((F*)a->p)[index]);
  763. }
  764. index++;
  765. return true;
  766. }
  767. lua_newtable(L);
  768. int size = a->d[a->r-rank+1];
  769. rank-=1;
  770. for(int i=0;i<size;i++) {
  771. bool dopush = pushNumberRecursive(L,rank,index,a);
  772. if (dopush) lua_rawseti(L,-2,i+1);
  773. }
  774. return true;
  775. }
  776. static bool pushNumber(lua_State *L, A a) {
  777. int n = a->n;
  778. if(n==0) return false;
  779. if(n==1) {
  780. if (a->t==It) {
  781. lua_pushinteger(L,*(I*)a->p);
  782. } else {
  783. lua_pushnumber(L,*(F*)a->p);
  784. }
  785. return true;
  786. }
  787. int rank = a->r;
  788. int index = 0;
  789. lua_newtable(L);
  790. int size = (rank<=1) ? a->n : a->d[0];
  791. for(int i=0;i<size;i++) {
  792. bool dopush = pushNumberRecursive(L,rank,index,a);
  793. if (dopush) lua_rawseti(L,-2,i+1);
  794. }
  795. return true;
  796. }
  797. static bool pushStringRecursive(lua_State *L, int rank, int& index, A a) {
  798. if (rank<=0) return false;
  799. if (rank==1) {
  800. int lim = a->d[a->r-2];
  801. int step = a->d[a->r-1];
  802. for(int i=0;i<lim;i++) {
  803. lua_pushlstring(L,(char*)a->p+index,step);
  804. index+=step;
  805. lua_rawseti(L,-2,i+1);
  806. }
  807. return false;
  808. }
  809. lua_newtable(L);
  810. int size = a->d[a->r-rank];
  811. rank-=1;
  812. for(int i=0;i<size;i++) {
  813. bool dopush = pushStringRecursive(L,rank,index,a);
  814. if (dopush) lua_rawseti(L,-2,i+1);
  815. }
  816. return true;
  817. }
  818. static bool pushString(lua_State *L, A a) {
  819. // return a string value to lua
  820. if (a->n==0) return false;
  821. if (a->r<=1) {
  822. lua_pushlstring(L,(char*)a->p,a->n);
  823. return true;
  824. }
  825. int rank = a->r;
  826. int index = 0;
  827. lua_newtable(L);
  828. for(int i=0;i<a->d[0];i++) {
  829. bool dopush = pushStringRecursive(L,--rank,index,a);
  830. if (dopush) lua_rawseti(L,-2,i+1);
  831. }
  832. return true;
  833. }
  834. static bool pushNestedRecursive(lua_State *L, int rank, int& index, A a) {
  835. if (rank<=1) {
  836. if (index>=a->n) return false;
  837. return pushValue(L,((A*)a->p)[index++]);
  838. }
  839. lua_newtable(L);
  840. int size = a->d[a->r-rank+1];
  841. rank-=1;
  842. for(int i=0;i<size;i++) {
  843. bool dopush = pushNestedRecursive(L,rank,index,a);
  844. if (dopush) lua_rawseti(L,-2,i+1);
  845. }
  846. return true;
  847. }
  848. static bool pushNested(lua_State *L, A a) {
  849. int rank = a->r;
  850. int index = 0;
  851. if (a->n==0) return false;
  852. lua_newtable(L);
  853. int size = (rank<=1) ? a->n : a->d[0];
  854. for(int i=0;i<size;i++) {
  855. bool dopush = pushNestedRecursive(L,rank,index,a);
  856. if (dopush) lua_rawseti(L,-2,i+1);
  857. }
  858. return true;
  859. }
  860. static bool pushSf(lua_State *L, A a) {
  861. // loop over syms - push key / value
  862. lua_newtable(L);
  863. A syms = (A)a->p[0];
  864. A vals = (A)a->p[1];
  865. int n = syms->n;
  866. for(int i=0;i<n;i++) {
  867. S s = XS(syms->p[i]);
  868. lua_pushstring(L,s->n);
  869. bool dopush = pushValue(L,(A)vals->p[i]);
  870. assert(dopush);
  871. lua_rawset(L, -3);
  872. }
  873. return true;
  874. }
  875. static bool pushValue(lua_State *L, A a) {
  876. if (QV(a)) a = (A)(XV(a)->a);
  877. switch(a->t) {
  878. case It: if (a->n==0) break; return pushNumber(L,a);
  879. case Ft: if (a->n==0) break; return pushNumber(L,a);
  880. case Ct: if (a->n==0) break; return pushString(L,a);
  881. case Et: if (a->n==0) break; if (ep_issf(a)) { return pushSf(L,a); } else { return pushNested(L,a); }
  882. case Xt: break;
  883. default: break;
  884. }
  885. return false;
  886. }
  887. static int value(lua_State *L) {
  888. A a = getA(L);
  889. bool dopush = pushValue(L,a);
  890. if (dopush) return 1;
  891. return 0;
  892. }
  893. static void addnewlines(A ct, string& str, const string& prefix, int offset) {
  894. // Convert an object to string - add newlines
  895. I d[9];
  896. mv(d,ct->d,ct->r);
  897. int k=ct->r-1;
  898. while(--k) { d[k]*=d[k+1]; }
  899. int an = ct->n;
  900. int step = ct->d[ct->r-1];
  901. int i = offset;
  902. if(an-i-step>0) {
  903. for(k=ct->r;--k&&!((an-i-step)%d[k]);) { str.append("\n"); str.append(prefix); }
  904. }
  905. }
  906. static string convert2str(A ct, const string& prefix) {
  907. // Convert an aobject to string
  908. string str;
  909. int an = ct->n;
  910. int step = ct->d[ct->r-1];
  911. for (int i=0;i<an;i+=step) {
  912. str.append(((C*)(ct->p))+i,step);
  913. addnewlines(ct,str,prefix,i);
  914. }
  915. return str;
  916. }
  917. static void nestedobj2string(A a, int& nestLevel, string& str) {
  918. // Convert a nested A object to a string
  919. int n = a->n;
  920. const char* prefix = "< ";
  921. const char* spaces = " ";
  922. for (int i=0; i<n; i++) {
  923. A a1 = (A)(a->p[i]);
  924. int localnest = nestLevel;
  925. if(a1->t==Et && !sym(a1)) {
  926. localnest++;
  927. nestedobj2string(a1,localnest,str);
  928. if(a->r>1) addnewlines(a,str,"",i);
  929. } else {
  930. A ct = (A)mth(a1);
  931. if (i==0) {
  932. for(int jj=0;jj<nestLevel;jj++) str.append(prefix);
  933. } else {
  934. for(int jj=0;jj<nestLevel-1;jj++) str.append(spaces);
  935. str.append(prefix);
  936. }
  937. if (ct->r>1) {
  938. string prefix2;
  939. for(int jj=0;jj<nestLevel;jj++) prefix2.append(spaces);
  940. str.append(convert2str(ct,prefix2).c_str());
  941. } else {
  942. str.append((C*)ct->p,ct->n);
  943. }
  944. str.append("\n");
  945. dc(ct);
  946. }
  947. }
  948. }
  949. static int collectgarbage(lua_State *L) {
  950. // Decrement a ref count on the A+ obj
  951. checkmem();
  952. void * ud = lua_touserdata(L,1);
  953. A a = *(A*)ud;
  954. if (QA(a)) {
  955. dc(a);
  956. } else if (QV(a)) {
  957. V v = XV(*(V*)(ud));
  958. if (v) {
  959. if(v->a) dc((A)v->a);
  960. free(v);
  961. }
  962. } else {
  963. luaL_error(L,"Error - freeing unknown var type");
  964. }
  965. checkmem();
  966. return 0;
  967. }
  968. static int unaryminus(lua_State *L) {
  969. // Evaluate fncode on the incoming args
  970. vector<Tok> toks;
  971. tokenizeArgs(L,toks,NoGrouping);
  972. Tok tmp = toks[1]; // Only first arg is valid
  973. toks.clear();
  974. toks.push_back(tmp);
  975. E e=(E)(ma(2+toks.size())); // 2+numArgs
  976. e->n=toks.size();
  977. e->f=op_umn;
  978. int size = toks.size();
  979. for(int i=0; i<size;i++) {
  980. A arg = getAObject(L,toks[i]);
  981. e->a[size-i-1]=(I)arg;
  982. }
  983. A res = doassign(L,(E)e);
  984. A* luares = (A*) lua_newuserdata(L, sizeof(A));
  985. luaL_getmetatable(L, "APLOBJ");
  986. lua_setmetatable(L, -2);
  987. (*luares) = res;
  988. return 1;
  989. }
  990. static int inlineop(lua_State *L, long fncode) {
  991. // Evaluate fncode on the incoming args
  992. vector<Tok> toks;
  993. tokenizeArgs(L,toks,NoGrouping);
  994. E e=(E)(ma(2+toks.size())); // 2+numArgs
  995. e->n=toks.size();
  996. e->f=fncode;
  997. int size = toks.size();
  998. for(int i=0; i<size;i++) {
  999. A arg = getAObject(L,toks[i]);
  1000. e->a[size-i-1]=(I)arg;
  1001. }
  1002. A res = doassign(L,(E)e);
  1003. A* luares = (A*) lua_newuserdata(L, sizeof(A));
  1004. luaL_getmetatable(L, "APLOBJ");
  1005. lua_setmetatable(L, -2);
  1006. (*luares) = res;
  1007. return 1;
  1008. }
  1009. static int plus(lua_State *L) { return inlineop(L,op_plus); }
  1010. static int minus(lua_State *L) { return inlineop(L,op_minus); }
  1011. static int multiply(lua_State *L) { return inlineop(L,op_multiply); }
  1012. static int divide(lua_State *L) { return inlineop(L,op_divide); }
  1013. static int power(lua_State *L) { return inlineop(L,op_pow); }
  1014. static int lessthaneq(lua_State *L) { return inlineop(L,op_le); }
  1015. static int lessthan(lua_State *L) { return inlineop(L,op_lt); }
  1016. static int strand(lua_State *L) { return inlineop(L,op_strand); }
  1017. static int equals(lua_State *L) {
  1018. // Return the value of the A+ operator "match" - either true or false
  1019. vector<Tok> toks;
  1020. tokenizeArgs(L,toks,NoGrouping);
  1021. E e=(E)(ma(2+toks.size())); // 2+numArgs
  1022. e->n=toks.size();
  1023. e->f=op_match;
  1024. int size = toks.size();
  1025. for(int i=0; i<size;i++) {
  1026. A arg = getAObject(L,toks[i]);
  1027. e->a[size-i-1]=(I)arg;
  1028. }
  1029. A res = doeval(L,(E)e);
  1030. lua_pushboolean(L, res->p[0]);
  1031. dc(res);
  1032. return 1;
  1033. }
  1034. static int length(lua_State *L) {
  1035. // Count - returns the length of the array
  1036. vector<Tok> toks;
  1037. tokenizeArgs(L,toks,NoGrouping);
  1038. E e=(E)(ma(2+1)); // 2+numArgs
  1039. e->n=1;
  1040. e->f=op_count;
  1041. e->a[0] = (I)getAObject(L,toks[1]); // First token passed in is a Null (?)
  1042. A res = doeval(L,(E)e);
  1043. lua_pushinteger(L, res->p[0]);
  1044. dc(res);
  1045. return 1;
  1046. }
  1047. static int symbol(lua_State *L) {
  1048. vector<Tok> toks;
  1049. tokenizeArgs(L,toks,NoGrouping);
  1050. int size = toks.size();
  1051. A z = gv(Et,size);
  1052. if (size==1) z->r=0;
  1053. for(int i=0;i<size;i++) {
  1054. assert((toks[i].iType==Char) && toks[i].iStr.size()==1);
  1055. z->p[size-i-1]=MS(si(toks[i].iStr[0].c_str()));
  1056. }
  1057. A* luares = (A*) lua_newuserdata(L, sizeof(A));
  1058. luaL_getmetatable(L, "APLOBJ");
  1059. lua_setmetatable(L, -2);
  1060. (*luares) = z;
  1061. return 1;
  1062. }
  1063. static int newindex(lua_State *L) {
  1064. if (lua_type(L,2) == LUA_TSTRING) {
  1065. lua_pushnil(L);
  1066. return 1;
  1067. }
  1068. return assign2SqrBrackets(L);
  1069. }
  1070. typedef A (*AFnPtr)(A);
  1071. static int inlinefunc(lua_State *L, AFnPtr fn) {
  1072. vector<Tok> toks;
  1073. tokenizeArgs(L,toks,NoGrouping);
  1074. Tok tuple;
  1075. for(unsigned int i=0; i<toks.size(); i++) {
  1076. if ((fn==ep_alsf) && (i%2!=0) && (toks[i].iType==Char) && (toks[i].iStr.size()==1)) {
  1077. A z = gv(Et,1);
  1078. z->p[0]=MS(si(toks[i].iStr[0].c_str()));
  1079. toks[i].iType = AObject;
  1080. toks[i].iA.push_back(z);
  1081. }
  1082. tuple.Append(getAObject(L,toks[i]));
  1083. }
  1084. A a = getAObject(L,tuple);
  1085. if (QV(a)) a = (A)((V)XV(a))->a;
  1086. A sf = fn(a);
  1087. if (q!=0) {
  1088. string errname((qs)? qs : "");
  1089. int errcode = q;
  1090. luaL_error(L,"luAPL error %d: %s",errcode, errname.c_str());
  1091. return 0;
  1092. }
  1093. V v=(V)malloc(sizeof(struct _v));memset(v,0,sizeof(struct _v));
  1094. v->a = (I)sf;
  1095. I* luares = (I*) lua_newuserdata(L, sizeof(A));
  1096. luaL_getmetatable(L, "APLOBJ");
  1097. lua_setmetatable(L, -2);
  1098. (*luares) = MV(v);
  1099. return 1;
  1100. }
  1101. static int alsf(lua_State *L) { return inlinefunc(L,ep_alsf); }
  1102. static int flat(lua_State *L) { return inlinefunc(L,ep_flat); }
  1103. static int sysexp(lua_State *L) { return inlinefunc(L,ep_exp); }
  1104. static int sysimp(lua_State *L) { return inlinefunc(L,ep_imp); }
  1105. static int ssr(lua_State *L) {
  1106. vector<Tok> toks;
  1107. tokenizeArgs(L,toks,NoGrouping);
  1108. A s = getAObject(L,toks[2]);
  1109. A t = getAObject(L,toks[1]);
  1110. A r = getAObject(L,toks[0]);
  1111. if (QV(s)) s = (A)((V)XV(s))->a;
  1112. if (QV(t)) t = (A)((V)XV(t))->a;
  1113. if (QV(r)) r = (A)((V)XV(r))->a;
  1114. A sf = ep_ssr(s,t,r);
  1115. if (q!=0) {
  1116. string errname((qs)? qs : "");
  1117. int errcode = q;
  1118. luaL_error(L,"luAPL error %d: %s",errcode, errname.c_str());
  1119. return 0;
  1120. }
  1121. V v=(V)malloc(sizeof(struct _v));memset(v,0,sizeof(struct _v));
  1122. v->a = (I)sf;
  1123. I* luares = (I*) lua_newuserdata(L, sizeof(A));
  1124. luaL_getmetatable(L, "APLOBJ");
  1125. lua_setmetatable(L, -2);
  1126. (*luares) = MV(v);
  1127. return 1;
  1128. }
  1129. static int ss(lua_State *L) {
  1130. vector<Tok> toks;
  1131. tokenizeArgs(L,toks,NoGrouping);
  1132. A s = getAObject(L,toks[1]);
  1133. A t = getAObject(L,toks[0]);
  1134. if (QV(s)) s = (A)((V)XV(s))->a;
  1135. if (QV(t)) t = (A)((V)XV(t))->a;
  1136. A sf = ep_ss(s,t);
  1137. if (q!=0) {
  1138. string errname((qs)? qs : "");
  1139. int errcode = q;
  1140. luaL_error(L,"luAPL error %d: %s",errcode, errname.c_str());
  1141. return 0;
  1142. }
  1143. V v=(V)malloc(sizeof(struct _v));memset(v,0,sizeof(struct _v));
  1144. v->a = (I)sf;
  1145. I* luares = (I*) lua_newuserdata(L, sizeof(A));
  1146. luaL_getmetatable(L, "APLOBJ");
  1147. lua_setmetatable(L, -2);
  1148. (*luares) = MV(v);
  1149. return 1;
  1150. }
  1151. static int issf(lua_State *L) {
  1152. vector<Tok> toks;
  1153. tokenizeArgs(L,toks,NoGrouping);
  1154. A a = getAObject(L,toks[0]);
  1155. if (QV(a)) a = (A)((V)XV(a))->a;
  1156. I res = ep_issf(a);
  1157. if (q!=0) {
  1158. string errname((qs)? qs : "");
  1159. int errcode = q;
  1160. luaL_error(L,"luAPL error %d: %s",errcode, errname.c_str());
  1161. return 0;
  1162. }
  1163. lua_pushinteger(L,res);
  1164. return 1;
  1165. }
  1166. int tostring(lua_State *L) {
  1167. // Convert an A object to a string
  1168. A a = getA(L);
  1169. A ct = NULL;
  1170. if (a->t==Et && !sym(a)) {
  1171. int nestLevel = 1;
  1172. string str="";
  1173. AFn::nestedobj2string(a,nestLevel,str);
  1174. str.resize(str.size()-1); // remove trailing \n
  1175. lua_pushstring(L,str.c_str());
  1176. } else {
  1177. ct = (A)mth(a);
  1178. string str;
  1179. if (ct->r>1) {
  1180. str = AFn::convert2str(ct,"");
  1181. } else {
  1182. str.append((C*)ct->p,ct->n);
  1183. }
  1184. lua_pushstring(L,str.c_str());
  1185. dc(ct);
  1186. }
  1187. return 1;
  1188. }
  1189. static int index(lua_State *L) {
  1190. // Call a method or evaluate square brackets on an aobject eg: x[0]
  1191. if (lua_type(L,2) == LUA_TSTRING) {
  1192. const char *key;
  1193. size_t ksize;
  1194. key = lua_tolstring(L,2,&ksize);
  1195. if (strcmp(key,"value") == 0) {
  1196. lua_pushcfunction(L,AFn::value);
  1197. return 1;
  1198. }
  1199. if (strcmp(key,"type") == 0) {
  1200. lua_pushcfunction(L,AFn::type2str);
  1201. return 1;
  1202. }
  1203. if (strcmp(key,"tostring") == 0) {
  1204. lua_pushcfunction(L,AFn::tostring);
  1205. return 1;
  1206. }
  1207. }
  1208. return sqrBrackets(L);
  1209. }
  1210. } // namespace AFn
  1211. extern "C"
  1212. const struct luaL_reg luapl [] = {
  1213. {"export", AFn::sysexp},
  1214. {"import", AFn::sysimp},
  1215. {"assign", assign},
  1216. {"debug", debug},
  1217. {"alsf", AFn::alsf},
  1218. {"assigninto", assigninto},
  1219. {"flat", AFn::flat},
  1220. {"issf", AFn::issf},
  1221. {"strand", AFn::strand},
  1222. {"symbol", AFn::symbol},
  1223. {"ssr",AFn::ssr},
  1224. {"ss",AFn::ss},
  1225. {NULL, NULL} /* sentinel */
  1226. };
  1227. #ifdef _WIN32
  1228. #define EXPORT __declspec(dllexport)
  1229. #else
  1230. #define EXPORT
  1231. #endif
  1232. extern "C"
  1233. void aplus_main(long argc, char** argv);
  1234. #ifndef _WIN32
  1235. void checkmem() {
  1236. }
  1237. #endif
  1238. extern "C"
  1239. EXPORT int luaopen_luapl (lua_State *L) {
  1240. const char* apldir = "./apl";
  1241. aplus_main(1, (char**)&apldir);
  1242. luaL_newmetatable(L, "APLOBJ");
  1243. lua_pushstring(L, "__index");
  1244. lua_pushcfunction(L, AFn::index);
  1245. lua_settable(L, -3);
  1246. lua_pushstring(L, "__newindex");
  1247. lua_pushcfunction(L, AFn::newindex);
  1248. lua_settable(L, -3);
  1249. lua_pushstring(L, "__gc");
  1250. lua_pushcfunction(L, AFn::collectgarbage);
  1251. lua_settable(L, -3);
  1252. lua_pushstring(L, "__add");
  1253. lua_pushcfunction(L, AFn::plus);
  1254. lua_settable(L, -3);
  1255. lua_pushstring(L, "__sub");
  1256. lua_pushcfunction(L, AFn::minus);
  1257. lua_settable(L, -3);
  1258. lua_pushstring(L, "__mul");
  1259. lua_pushcfunction(L, AFn::multiply);
  1260. lua_settable(L, -3);
  1261. lua_pushstring(L, "__div");
  1262. lua_pushcfunction(L, AFn::divide);
  1263. lua_settable(L, -3);
  1264. lua_pushstring(L, "__pow");
  1265. lua_pushcfunction(L, AFn::power);
  1266. lua_settable(L, -3);
  1267. lua_pushstring(L, "__unm");
  1268. lua_pushcfunction(L, AFn::unaryminus);
  1269. lua_settable(L, -3);
  1270. /* - broken only work if both args are userdata and returns a boolean.
  1271. lua_pushstring(L, "__lt");
  1272. lua_pushcfunction(L, AFn::lessthan);
  1273. lua_settable(L, -3);
  1274. lua_pushstring(L, "__le");
  1275. lua_pushcfunction(L, AFn::lessthaneq);
  1276. lua_settable(L, -3);
  1277. */
  1278. lua_pushstring(L, "__eq");
  1279. lua_pushcfunction(L, AFn::equals);
  1280. lua_settable(L, -3);
  1281. lua_pushstring(L, "__len");
  1282. lua_pushcfunction(L, AFn::length);
  1283. lua_settable(L, -3);
  1284. lua_pushstring(L, "__tostring");
  1285. lua_pushcfunction(L, AFn::tostring);
  1286. lua_settable(L, -3);
  1287. int i = 0;
  1288. while (APL_OPTABLE[i].name != NULL)
  1289. registerOperator(L,&APL_OPTABLE[i++]);
  1290. luaL_openlib(L, "luapl", luapl, 0);
  1291. return 1;
  1292. }