verm.lua 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. local _G=_G
  2. local ipairs=ipairs
  3. local select=select
  4. local pairs=pairs
  5. local type = type
  6. local unpack=unpack
  7. local logError = logError
  8. local DATA = DATA
  9. --/////////////////////////
  10. local function table_print (tt, done)
  11. done = done or {}
  12. if type(tt) == "table" then
  13. local sb = {}
  14. table.insert(sb, "{");
  15. for key, value in pairs (tt) do
  16. if type (value) == "table" and not done [value] then
  17. done [value] = true
  18. table.insert(sb, key .. ":{");
  19. table.insert(sb, table_print (value, done))
  20. table.insert(sb, "}");
  21. else
  22. table.insert(sb, string.format(
  23. "%s:\"%s\"", tostring (key), tostring(value)))
  24. end
  25. table.insert(sb, ",");
  26. end
  27. table.insert(sb, "}");
  28. m = getmetatable(tt);
  29. if m and m.__index then
  30. table.insert(sb, table_print (m.__index, done));
  31. end
  32. return table.concat(sb)
  33. else
  34. return tt .. ""
  35. end
  36. end
  37. local function to_string( tbl )
  38. if "nil" == type( tbl ) then
  39. return tostring(nil)
  40. elseif "table" == type( tbl ) then
  41. return table_print(tbl)
  42. elseif "string" == type( tbl ) then
  43. return tbl
  44. else
  45. return tostring(tbl)
  46. end
  47. end
  48. --/////////////////////////
  49. local VERM = {}
  50. local function createEnv(parent, current)
  51. return setmetatable(
  52. current or {},
  53. {
  54. __parent = parent,
  55. __index = parent,
  56. __newindex = function(t, k ,v)
  57. if type(k) ~= "string" then
  58. error("String key for env. table required, but got:"..to_string(k))
  59. end
  60. local function setOnFirstHit(t, k, v)
  61. local vv = rawget(t, k)
  62. if vv~= nil then rawset(t, k, v); return true end
  63. local m = getmetatable(t)
  64. if not m then return false end --assume top
  65. local p = m.__parent
  66. if not p then
  67. return false
  68. else
  69. return setOnFirstHit(p, k, v)
  70. end
  71. end
  72. if not setOnFirstHit(t, k, v) then
  73. rawset(t, k, v)
  74. end
  75. end
  76. }
  77. )
  78. end
  79. local function isNIL(v)
  80. return (type(v) == "table") and (next(v) == nil)
  81. end
  82. local function prognForm(e, ...)
  83. --eval each argument, return last result
  84. local argc = select('#',...)
  85. if argc == 0 then return {} end
  86. for n = 1, argc - 1 do
  87. VERM:eval(e, (select(n,...)))
  88. end
  89. return VERM:eval(e, (select(argc,...)))
  90. end
  91. local function lambdaOrMacro(e, isMacro, args, ...)
  92. --TODO: get rid of pack-unpack
  93. local body = {...}
  94. local oldEnv = e
  95. local ret = function(e, ...)
  96. -- we need a function that have parameters with names from `args` table
  97. -- pack parameters from '...' and bind to new environment
  98. local newEnv = createEnv(oldEnv, {})
  99. for i, v in ipairs(args) do
  100. local p = select(i,...)
  101. if isMacro then
  102. newEnv[v] = p
  103. else
  104. newEnv[v] = VERM:evalValue(e, p)
  105. end
  106. end
  107. if isMacro then
  108. local buffer = {}
  109. for _, v in ipairs(body) do
  110. table.insert(buffer, (VERM:eval(newEnv, v)))
  111. end
  112. return prognForm(newEnv, unpack(buffer))
  113. else
  114. return prognForm(newEnv, unpack(body))
  115. end
  116. end
  117. return ret
  118. end
  119. local function lambdaForm(e, args, ...)
  120. return lambdaOrMacro(e, false, args, ...)
  121. end
  122. local function defunForm(e, name, args, ...)
  123. local ret = lambdaOrMacro(e, false, args, ...)
  124. e[name] = ret
  125. return ret
  126. end
  127. local function defmacroForm(e, name, args, ...)
  128. local ret = lambdaOrMacro(e, true, args, ...)
  129. e[name] = ret
  130. return ret
  131. end
  132. local function backquoteEval(e, v)
  133. if isNIL(v) then
  134. return v
  135. elseif type(v) == "table" then
  136. local car = v[1]
  137. if car == "," then
  138. return VERM:evalValue(e, v[2])
  139. else
  140. local ret = {}
  141. for _, v in ipairs(v) do
  142. table.insert(ret, (backquoteEval(e, v)))
  143. end
  144. return ret
  145. end
  146. else
  147. return v
  148. end
  149. end
  150. local specialForms =
  151. {
  152. ["<"] = function(e, lhs, rhs)
  153. lhs = VERM:evalValue(e, lhs)
  154. rhs = VERM:evalValue(e, rhs)
  155. if lhs < rhs then
  156. return lhs
  157. else
  158. return {}
  159. end
  160. end,
  161. ["<="] = function(e, lhs, rhs)
  162. lhs = VERM:evalValue(e, lhs)
  163. rhs = VERM:evalValue(e, rhs)
  164. if lhs <= rhs then
  165. return lhs
  166. else
  167. return {}
  168. end
  169. end,
  170. [">"] = function(e, lhs, rhs)
  171. lhs = VERM:evalValue(e, lhs)
  172. rhs = VERM:evalValue(e, rhs)
  173. if lhs > rhs then
  174. return lhs
  175. else
  176. return {}
  177. end
  178. end,
  179. [">="] = function(e, lhs, rhs)
  180. lhs = VERM:evalValue(e, lhs)
  181. rhs = VERM:evalValue(e, rhs)
  182. if lhs >= rhs then
  183. return lhs
  184. else
  185. return {}
  186. end
  187. end,
  188. ["="] = function(e, lhs, rhs)
  189. lhs = VERM:evalValue(e, lhs)
  190. rhs = VERM:evalValue(e, rhs)
  191. if lhs == rhs then
  192. return lhs
  193. else
  194. return {}
  195. end
  196. end,
  197. ["+"] = function(e, ...)
  198. local ret = 0
  199. for n=1,select('#',...) do
  200. local v = VERM:evalValue(e, (select(n,...)))
  201. ret = ret + v
  202. end
  203. return ret
  204. end,
  205. ["*"] = function(e, ...)
  206. local ret = 1
  207. for n=1,select('#',...) do
  208. local v = VERM:evalValue(e, (select(n,...)))
  209. ret = ret * v
  210. end
  211. return ret
  212. end,
  213. ["-"] = function(e, lhs, rhs)
  214. lhs = VERM:evalValue(e, lhs)
  215. rhs = VERM:evalValue(e, rhs)
  216. return lhs - rhs
  217. end,
  218. ["/"] = function(e, lhs, rhs)
  219. lhs = VERM:evalValue(e, lhs)
  220. rhs = VERM:evalValue(e, rhs)
  221. return lhs / rhs
  222. end,
  223. ["%"] = function(e, lhs, rhs)
  224. lhs = VERM:evalValue(e, lhs)
  225. rhs = VERM:evalValue(e, rhs)
  226. return lhs % rhs
  227. end,
  228. -- ["comma-unlist"] = function(e, ...) end,
  229. ["`"] = backquoteEval,
  230. -- ["get-func"] = function(e, ...) end,
  231. ["'"] = function(e, v)
  232. return v
  233. end,
  234. ["if"] = function(e, cond, v1, v2)
  235. cond = VERM:evalValue(e, cond)
  236. if isNIL(cond) then
  237. return VERM:evalValue(e, v2)
  238. else
  239. return VERM:evalValue(e, v1)
  240. end
  241. end,
  242. -- ["set"] = function(e, ...) end,
  243. -- ["setf"] = function(e, ...) end,
  244. ["setq"] = function(e, name, value)
  245. e[name] = VERM:evalValue(e, value)
  246. end,
  247. ["lambda"] = lambdaForm,
  248. ["defun"] = defunForm,
  249. ["progn"] = prognForm,
  250. ["defmacro"] = defmacroForm,
  251. ["do"] = function(e, cond, body)
  252. local c = VERM:eval(e, cond)
  253. while not isNIL(c) do
  254. VERM:eval(e, body)
  255. c = VERM:eval(e, cond)
  256. end
  257. return {}
  258. end,
  259. ["car"] = function(e, list)
  260. list = VERM:eval(e, list)
  261. return list[1] or {}
  262. end,
  263. ["cdr"] = function(e, list)
  264. list = VERM:eval(e, list)
  265. local ret = {}
  266. for i, v in ipairs(list) do
  267. if i > 1 then
  268. table.insert(ret, v)
  269. end
  270. end
  271. return ret
  272. end,
  273. ["list"] = function(e, ...)
  274. local ret = {}
  275. for n=1,select('#',...) do
  276. local v = VERM:evalValue(e, (select(n,...)))
  277. table.insert(ret, v)
  278. end
  279. return ret
  280. end,
  281. ["setq-erm"] = function(e, var, varIndex, value)
  282. local v = VERM:evalValue(e, value)
  283. DATA.ERM[var][tostring(VERM:evalValue(e, varIndex))] = v
  284. return v
  285. end,
  286. }
  287. function VERM:evalValue(e, v)
  288. if isNIL(v) then
  289. return v
  290. elseif type(v) == "table" then
  291. return self:eval(e, v)
  292. elseif type(v) == "string" then
  293. return e[v]
  294. elseif type(v) == "function" then
  295. error("evalValue do not accept functions")
  296. else
  297. return v
  298. end
  299. end
  300. function VERM:eval(e, t)
  301. if type(t) ~= "table" then
  302. logError("Not valid form: ".. to_string(t))
  303. return {}
  304. end
  305. local car = t[1]
  306. local origCar = car
  307. if type(car) == "string" then
  308. car = e[car]
  309. end
  310. if type(car) == "table" then
  311. car = self:eval(e, car)
  312. end
  313. if type(car) == "function" then
  314. return car(e, unpack(t,2))
  315. else
  316. logError(to_string(t) .. " is not callable. Car()="..to_string(car))
  317. logError("Env:"..to_string(e))
  318. return {}
  319. end
  320. end
  321. function VERM:E(line)
  322. self:eval(self.topEnv, line)
  323. end
  324. VERM.topEnv = createEnv(specialForms)
  325. return VERM