/LispMacro.cpp

https://bitbucket.org/hardtack/resoup · C++ · 482 lines · 445 code · 27 blank · 10 comment · 90 complexity · 452386912c10eeedc4e2cddfe0baeb86 MD5 · raw file

  1. /*
  2. * LispMacro.cpp
  3. * resoup
  4. *
  5. * Created by ??? on 10. 9. 2..
  6. * Copyright 2010 Unplug. All rights reserved.
  7. *
  8. */
  9. #include "LispMacro.h"
  10. #include "LispQuote.h"
  11. #include "Evaluator.h"
  12. #include "LispBoolean.h"
  13. #include "LispString.h"
  14. #include <iostream>
  15. #include "Functions.h"
  16. using namespace Functions;
  17. using namespace Evaluator;
  18. int LispMacro::getClassIdentifier(){
  19. return LISPMACRO;
  20. }
  21. LispObject* DefineMacro::copy(){
  22. return new DefineMacro(*this);
  23. }
  24. LispObject* DefineMacro::callMacro(LispObject **args, int argsSize, LispEnvironment *env) throw (DefineNotAllowed &,
  25. NumberOfArgumentsDoesNotMatchException &,
  26. TypeOfArgumentDoesNotMatchException &,
  27. Exception &){
  28. if (argsSize != 2){
  29. DefineNotAllowed e;
  30. e.syntaxError = true;
  31. throw e;
  32. } else if (args[0]->getClassIdentifier() == LISPSYMBOL) {
  33. LispObject *evaluated = evaluate(args[1], env);
  34. if(evaluated->getClassIdentifier() == LISPMACRO){
  35. delete evaluated;
  36. DefineNotAllowed e;
  37. e.syntaxError = true;
  38. throw e;
  39. }
  40. LispSymbolValuePair *svp = new LispSymbolValuePair(((LispSymbol *)args[0])->getName(), evaluated);
  41. env->addSymbolValuePair(svp);
  42. } else if (args[0]->getClassIdentifier() == LISPLIST) {
  43. // Change to lambda
  44. LispList *list = (LispList *)args[0];
  45. // Syntax check
  46. if (list->getSize() == 0) {
  47. DefineNotAllowed e;
  48. e.syntaxError = true;
  49. throw e;
  50. }
  51. for (int i = 0; i < list->getSize(); i++) {
  52. LispObject *element = list->getElement(i);
  53. if (element->getClassIdentifier() != LISPSYMBOL) {
  54. DefineNotAllowed e;
  55. e.syntaxError = true;
  56. throw e;
  57. }
  58. delete element;
  59. }
  60. LispSymbol *name = (LispSymbol *)list->getElement(0);
  61. LispList *argList = new LispList();
  62. for (int i = 1; i < list->getSize(); i++) {
  63. LispSymbol *arg = (LispSymbol *)list->getElement(i);
  64. argList->addElement(arg);
  65. delete arg;
  66. }
  67. LispList *lambdaList = new LispList();
  68. LambdaMacro *lambda = new LambdaMacro();
  69. lambdaList->addElement(lambda);
  70. delete lambda;
  71. lambdaList->addElement(argList);
  72. delete argList;
  73. lambdaList->addElement(args[1]);
  74. env->addSymbolValuePair(new LispSymbolValuePair(name->getName(), evaluate(lambdaList, env)));
  75. delete lambdaList;
  76. } else {
  77. DefineNotAllowed e;
  78. e.syntaxError = true;
  79. throw e;
  80. }
  81. return new LispNil();
  82. }
  83. LispObject* LambdaMacro::copy(){
  84. return new LambdaMacro(*this);
  85. }
  86. LispObject* LambdaMacro::callMacro(LispObject **args, int argsSize, LispEnvironment *env) throw (NumberOfArgumentsDoesNotMatchException &, TypeOfArgumentDoesNotMatchException &, Exception &){
  87. char *name = stringcpy("lambda");
  88. if(argsSize != 2){
  89. NumberOfArgumentsDoesNotMatchException e;
  90. e.has = argsSize;
  91. e.required = 2;
  92. e.maxRequired = 2;
  93. e.name = stringcpy(name);
  94. throw e;
  95. }
  96. LispObject *first = args[0];
  97. LispObject *second = args[1];
  98. if (first->getClassIdentifier() != LISPLIST) {
  99. TypeOfArgumentDoesNotMatchException e;
  100. e.has = first->getClassIdentifier();
  101. e.required = LISPLIST;
  102. e.at = 1;
  103. e.name = stringcpy(name);
  104. throw e;
  105. }
  106. switch (first->getClassIdentifier()) {
  107. case LISPLIST:{
  108. LispList *list = (LispList *)first;
  109. for (int i = 0; i < list->getSize(); i++) {
  110. LispObject *element = list->getElement(i);
  111. int ci = element->getClassIdentifier();
  112. delete element;
  113. if (ci != LISPSYMBOL) {
  114. TypeOfArgumentDoesNotMatchException e;
  115. e.has = ci;
  116. e.required = LISPSYMBOL;
  117. e.at = i + 1;
  118. e.name = stringcpy(name);
  119. throw e;
  120. }
  121. }
  122. LispProcedure *procedure = new LispProcedure(list->getSize(), list->getSize(), (LispList *)second, env);
  123. for (int i = 0; i < list->getSize(); i++) {
  124. LispSymbol *element = (LispSymbol *)list->getElement(i);
  125. procedure->addNameOfArgument(element->getName());
  126. delete element;
  127. }
  128. return procedure;
  129. }
  130. default:{
  131. if (second->getClassIdentifier() != LISPLIST) {
  132. TypeOfArgumentDoesNotMatchException e;
  133. e.has = second->getClassIdentifier();
  134. e.required = LISPLIST;
  135. e.at = 2;
  136. e.name = stringcpy(name);
  137. throw e;
  138. }
  139. return new LispProcedure(0 , 0, (LispList *)second, env);
  140. }
  141. }
  142. }
  143. LispObject* CondMacro::copy(){
  144. return new CondMacro(*this);
  145. }
  146. LispObject* CondMacro::callMacro(LispObject **args, int argsSize, LispEnvironment *env) throw (NumberOfArgumentsDoesNotMatchException &, TypeOfArgumentDoesNotMatchException &, Exception &){
  147. for (int i = 0; i < argsSize; i++) {
  148. if (args[i]->getClassIdentifier() != LISPLIST) {
  149. TypeOfArgumentDoesNotMatchException e;
  150. e.at = i + 1;
  151. e.has = args[i]->getClassIdentifier();
  152. e.required = LISPLIST;
  153. e.name = stringcpy("cond");
  154. throw e;
  155. } else if (((LispList *)args[i])->getSize() != 2) {
  156. NumberOfArgumentsDoesNotMatchException e;
  157. e.has = ((LispList *)args[i])->getSize();
  158. e.required = 2;
  159. e.maxRequired = 2;
  160. e.name = stringcpy("name");
  161. throw e;
  162. }
  163. }
  164. return evaluate(condToIf(0, (LispList **)args, argsSize), env);
  165. }
  166. LispList* CondMacro::condToIf(int i, LispList **args, int argsSize){
  167. if(i == argsSize - 1){
  168. LispList *ifList = new LispList();
  169. IfMacro *ifmacro = new IfMacro();
  170. ifList->addElement(ifmacro);
  171. delete ifmacro;
  172. LispObject *boolean = args[i]->getElement(0);
  173. ifList->addElement(boolean);
  174. delete boolean;
  175. LispObject *first = args[i]->getElement(1);
  176. ifList->addElement(first);
  177. delete first;
  178. LispNil *nil = new LispNil();
  179. ifList->addElement(nil);
  180. delete nil;
  181. return ifList;
  182. }else {
  183. LispList *ifList = new LispList();
  184. IfMacro *ifmacro = new IfMacro();
  185. ifList->addElement(ifmacro);
  186. delete ifmacro;
  187. LispObject *boolean = args[i]->getElement(0);
  188. ifList->addElement(boolean);
  189. delete boolean;
  190. LispObject *first = args[i]->getElement(1);
  191. ifList->addElement(first);
  192. delete first;
  193. ifList->addElement(condToIf(i + 1, args, argsSize));
  194. return ifList;
  195. }
  196. }
  197. LispObject* IfMacro::copy(){
  198. return new IfMacro(*this);
  199. }
  200. LispObject* IfMacro::callMacro(LispObject **args, int argsSize, LispEnvironment *env) throw (NumberOfArgumentsDoesNotMatchException &, Exception &){
  201. if (argsSize != 3) {
  202. NumberOfArgumentsDoesNotMatchException e;
  203. e.has = argsSize;
  204. e.maxRequired = 3;
  205. e.required = 3;
  206. e.name = stringcpy("if");
  207. throw e;
  208. }
  209. bool boolean;
  210. LispObject *boolObj = evaluate(args[0], env);
  211. int ci = boolObj->getClassIdentifier();
  212. if (ci == LISPBOOLEAN) {
  213. boolean = ((LispBoolean *) boolObj)->getBool();
  214. } else if (ci == LISPNIL){
  215. boolean = false;
  216. } else {
  217. boolean = true;
  218. }
  219. if (boolean) {
  220. return evaluate(args[1], env);
  221. }
  222. else {
  223. return evaluate(args[2], env);
  224. }
  225. }
  226. LispObject* QuoteMacro::copy(){
  227. return new QuoteMacro(*this);
  228. }
  229. LispObject* QuoteMacro::callMacro(LispObject **args, int argsSize, LispEnvironment *env) throw (NumberOfArgumentsDoesNotMatchException &, Exception &){
  230. if (argsSize != 1) {
  231. NumberOfArgumentsDoesNotMatchException e;
  232. e.has = argsSize;
  233. e.maxRequired = 1;
  234. e.required = 1;
  235. e.name = stringcpy("quote");
  236. throw e;
  237. }
  238. return ((LispQuote *)args[0])->getItem();
  239. }
  240. LispObject* BeginMacro::copy(){
  241. return new BeginMacro(*this);
  242. }
  243. LispObject* BeginMacro::callMacro(LispObject **args, int argsSize, LispEnvironment *env) throw (NumberOfArgumentsDoesNotMatchException &, Exception &){
  244. if (argsSize == 0){
  245. NumberOfArgumentsDoesNotMatchException e;
  246. e.has = 0;
  247. e.name = stringcpy("begin");
  248. e.required = 1;
  249. e.maxRequired = UNLIMITED_ARGUMENTS;
  250. throw e;
  251. }
  252. for (int i = 0; i < argsSize - 1; i++) {
  253. evaluate(args[i], env);
  254. }
  255. return evaluate(args[argsSize - 1], env);
  256. }
  257. LispObject* LetMacro::copy(){
  258. return new LetMacro(*this);
  259. }
  260. LispObject* LetMacro::callMacro(LispObject **args, int argsSize, LispEnvironment *env) throw (NumberOfArgumentsDoesNotMatchException &, TypeOfArgumentDoesNotMatchException &, Exception &){
  261. char *name = stringcpy("let");
  262. if (argsSize != 2){
  263. NumberOfArgumentsDoesNotMatchException e;
  264. e.has = argsSize;
  265. e.required = 2;
  266. e.maxRequired = 2;
  267. e.name = name;
  268. throw e;
  269. }
  270. if (args[0]->getClassIdentifier() != LISPLIST){
  271. TypeOfArgumentDoesNotMatchException e;
  272. e.at = 0 + 1;
  273. e.has = args[0]->getClassIdentifier();
  274. e.required = LISPLIST;
  275. e.name = name;
  276. throw e;
  277. }
  278. int itemSize = ((LispList *)args[0])->getSize();
  279. LispObject **items = new LispObject*[itemSize];
  280. LispEnvironment *newEnv = new LispEnvironment(env);
  281. for (int i = 0; i < itemSize; i++) {
  282. items[i] = ((LispList *)args[0])->getElement(i);
  283. if (items[i]->getClassIdentifier() != LISPLIST) {
  284. TypeOfArgumentDoesNotMatchException e;
  285. e.has = items[i]->getClassIdentifier();
  286. for (int j = 0; j < i + 1; j++) {
  287. delete items[j];
  288. }
  289. delete[] items;
  290. e.required = LISPLIST;
  291. e.name = stringcpy("List");
  292. e.at = i;
  293. throw e;
  294. }
  295. if (((LispList *)items[i])->getSize() != 2) {
  296. NumberOfArgumentsDoesNotMatchException e;
  297. e.has = ((LispList *)items[i])->getSize();
  298. for (int j = 0; j < i + 1; j++) {
  299. delete items[j];
  300. }
  301. delete[] items;
  302. e.required = 2;
  303. e.maxRequired = 2;
  304. e.name = stringcpy("List");
  305. throw e;
  306. }
  307. LispObject *symbol = ((LispList *)items[i])->getElement(0);
  308. if (symbol->getClassIdentifier() != LISPSYMBOL) {
  309. TypeOfArgumentDoesNotMatchException e;
  310. e.has = items[i]->getClassIdentifier();
  311. for (int j = 0; j < i + 1; j++) {
  312. delete items[j];
  313. }
  314. delete[] items;
  315. e.required = LISPSYMBOL;
  316. e.name = stringcpy("List");
  317. e.at = 0;
  318. throw e;
  319. }
  320. LispObject *item = evaluate(((LispList *)items[i])->getElement(1), env);
  321. newEnv->addSymbolValuePair(new LispSymbolValuePair(((LispSymbol *)symbol)->getName(), item));
  322. }
  323. return evaluate(args[1], newEnv);
  324. }
  325. LispObject* LetAsteriskMacro::copy(){
  326. return new LetAsteriskMacro(*this);
  327. }
  328. LispObject* LetAsteriskMacro::callMacro(LispObject **args, int argsSize, LispEnvironment *env) throw (NumberOfArgumentsDoesNotMatchException &, TypeOfArgumentDoesNotMatchException &, Exception &){
  329. char *name = stringcpy("let");
  330. if (argsSize != 2){
  331. NumberOfArgumentsDoesNotMatchException e;
  332. e.has = argsSize;
  333. e.required = 2;
  334. e.maxRequired = 2;
  335. e.name = name;
  336. throw e;
  337. }
  338. if (args[0]->getClassIdentifier() != LISPLIST){
  339. TypeOfArgumentDoesNotMatchException e;
  340. e.at = 0 + 1;
  341. e.has = args[0]->getClassIdentifier();
  342. e.required = LISPLIST;
  343. e.name = name;
  344. throw e;
  345. }
  346. int itemSize = ((LispList *)args[0])->getSize();
  347. LispObject **items = new LispObject*[itemSize];
  348. LispEnvironment *newEnv = new LispEnvironment(env);
  349. for (int i = 0; i < itemSize; i++) {
  350. items[i] = ((LispList *)args[0])->getElement(i);
  351. if (items[i]->getClassIdentifier() != LISPLIST) {
  352. TypeOfArgumentDoesNotMatchException e;
  353. e.has = items[i]->getClassIdentifier();
  354. for (int j = 0; j < i + 1; j++) {
  355. delete items[j];
  356. }
  357. delete[] items;
  358. e.required = LISPLIST;
  359. e.name = stringcpy("List");
  360. e.at = i;
  361. throw e;
  362. }
  363. if (((LispList *)items[i])->getSize() != 2) {
  364. NumberOfArgumentsDoesNotMatchException e;
  365. e.has = ((LispList *)items[i])->getSize();
  366. for (int j = 0; j < i + 1; j++) {
  367. delete items[j];
  368. }
  369. delete[] items;
  370. e.required = 2;
  371. e.maxRequired = 2;
  372. e.name = stringcpy("List");
  373. throw e;
  374. }
  375. LispObject *symbol = ((LispList *)items[i])->getElement(0);
  376. if (symbol->getClassIdentifier() != LISPSYMBOL) {
  377. TypeOfArgumentDoesNotMatchException e;
  378. e.has = items[i]->getClassIdentifier();
  379. for (int j = 0; j < i + 1; j++) {
  380. delete items[j];
  381. }
  382. delete[] items;
  383. e.required = LISPSYMBOL;
  384. e.name = stringcpy("List");
  385. e.at = 0;
  386. throw e;
  387. }
  388. LispObject *item = evaluate(((LispList *)items[i])->getElement(1), newEnv);
  389. newEnv->addSymbolValuePair(new LispSymbolValuePair(((LispSymbol *)symbol)->getName(), item));
  390. }
  391. return evaluate(args[1], newEnv);
  392. }
  393. LispObject* SetExcalMacro::copy(){
  394. return new SetExcalMacro(*this);
  395. }
  396. LispObject* SetExcalMacro::callMacro(LispObject **args, int argsSize, LispEnvironment *env) throw (NumberOfArgumentsDoesNotMatchException &,
  397. TypeOfArgumentDoesNotMatchException &,
  398. DefineNotAllowed &,
  399. Exception &){
  400. if (argsSize != 2) {
  401. NumberOfArgumentsDoesNotMatchException e;
  402. e.has = argsSize;
  403. e.required = 2;
  404. e.maxRequired = 2;
  405. e.name = stringcpy("set!");
  406. throw e;
  407. }
  408. if (args[0]->getClassIdentifier() != LISPSYMBOL) {
  409. TypeOfArgumentDoesNotMatchException e;
  410. e.has = args[0]->getClassIdentifier();
  411. e.required = LISPSYMBOL;
  412. e.name = stringcpy("set!");
  413. e.at = 1;
  414. throw e;
  415. }
  416. LispSymbolValuePair **ptrSvp = env->getSymbolValuePairDoublePointer(((LispSymbol *)args[0])->getName());
  417. LispSymbolValuePair *tmp = *ptrSvp;
  418. LispObject* evaluated = evaluate(args[1], env);
  419. if (evaluated->getClassIdentifier() == LISPMACRO){
  420. delete evaluated;
  421. DefineNotAllowed e;
  422. e.syntaxError = true;
  423. throw e;
  424. }
  425. *ptrSvp = new LispSymbolValuePair(((LispSymbol *)args[0])->getName(), evaluated);
  426. delete tmp;
  427. return new LispNil();
  428. }
  429. LispObject* LoadMacro::copy(){
  430. return new LoadMacro(*this);
  431. }
  432. LispObject* LoadMacro::callMacro(LispObject **args, int argsSize, LispEnvironment *env) throw (NumberOfArgumentsDoesNotMatchException &, TypeOfArgumentDoesNotMatchException &, Exception &){
  433. if (argsSize != 1) {
  434. NumberOfArgumentsDoesNotMatchException e;
  435. e.has = argsSize;
  436. e.required = 1;
  437. e.maxRequired = 1;
  438. e.name = stringcpy("load");
  439. throw e;
  440. }
  441. if (args[0]->getClassIdentifier() != LISPSTRING) {
  442. TypeOfArgumentDoesNotMatchException e;
  443. e.has = args[0]->getClassIdentifier();
  444. e.name = stringcpy("load");
  445. e.required = LISPSTRING;
  446. e.at = 1;
  447. throw e;
  448. }
  449. char *expression = loadFile(((LispString *)args[0])->getString());
  450. if(!run(expression, env)){
  451. std::cout << "Exit by external file" << std::endl;
  452. exit(0);
  453. }
  454. return new LispNil();
  455. }