/LispMacro.cpp
https://bitbucket.org/hardtack/resoup · C++ · 482 lines · 445 code · 27 blank · 10 comment · 90 complexity · 452386912c10eeedc4e2cddfe0baeb86 MD5 · raw file
- /*
- * LispMacro.cpp
- * resoup
- *
- * Created by ??? on 10. 9. 2..
- * Copyright 2010 Unplug. All rights reserved.
- *
- */
- #include "LispMacro.h"
- #include "LispQuote.h"
- #include "Evaluator.h"
- #include "LispBoolean.h"
- #include "LispString.h"
- #include <iostream>
- #include "Functions.h"
- using namespace Functions;
- using namespace Evaluator;
- int LispMacro::getClassIdentifier(){
- return LISPMACRO;
- }
- LispObject* DefineMacro::copy(){
- return new DefineMacro(*this);
- }
- LispObject* DefineMacro::callMacro(LispObject **args, int argsSize, LispEnvironment *env) throw (DefineNotAllowed &,
- NumberOfArgumentsDoesNotMatchException &,
- TypeOfArgumentDoesNotMatchException &,
- Exception &){
- if (argsSize != 2){
- DefineNotAllowed e;
- e.syntaxError = true;
- throw e;
- } else if (args[0]->getClassIdentifier() == LISPSYMBOL) {
- LispObject *evaluated = evaluate(args[1], env);
- if(evaluated->getClassIdentifier() == LISPMACRO){
- delete evaluated;
- DefineNotAllowed e;
- e.syntaxError = true;
- throw e;
- }
- LispSymbolValuePair *svp = new LispSymbolValuePair(((LispSymbol *)args[0])->getName(), evaluated);
- env->addSymbolValuePair(svp);
- } else if (args[0]->getClassIdentifier() == LISPLIST) {
- // Change to lambda
- LispList *list = (LispList *)args[0];
- // Syntax check
- if (list->getSize() == 0) {
- DefineNotAllowed e;
- e.syntaxError = true;
- throw e;
- }
- for (int i = 0; i < list->getSize(); i++) {
- LispObject *element = list->getElement(i);
- if (element->getClassIdentifier() != LISPSYMBOL) {
- DefineNotAllowed e;
- e.syntaxError = true;
- throw e;
- }
- delete element;
- }
- LispSymbol *name = (LispSymbol *)list->getElement(0);
- LispList *argList = new LispList();
- for (int i = 1; i < list->getSize(); i++) {
- LispSymbol *arg = (LispSymbol *)list->getElement(i);
- argList->addElement(arg);
- delete arg;
- }
- LispList *lambdaList = new LispList();
- LambdaMacro *lambda = new LambdaMacro();
- lambdaList->addElement(lambda);
- delete lambda;
- lambdaList->addElement(argList);
- delete argList;
- lambdaList->addElement(args[1]);
- env->addSymbolValuePair(new LispSymbolValuePair(name->getName(), evaluate(lambdaList, env)));
- delete lambdaList;
- } else {
- DefineNotAllowed e;
- e.syntaxError = true;
- throw e;
- }
- return new LispNil();
- }
- LispObject* LambdaMacro::copy(){
- return new LambdaMacro(*this);
- }
- LispObject* LambdaMacro::callMacro(LispObject **args, int argsSize, LispEnvironment *env) throw (NumberOfArgumentsDoesNotMatchException &, TypeOfArgumentDoesNotMatchException &, Exception &){
- char *name = stringcpy("lambda");
- if(argsSize != 2){
- NumberOfArgumentsDoesNotMatchException e;
- e.has = argsSize;
- e.required = 2;
- e.maxRequired = 2;
- e.name = stringcpy(name);
- throw e;
- }
- LispObject *first = args[0];
- LispObject *second = args[1];
- if (first->getClassIdentifier() != LISPLIST) {
- TypeOfArgumentDoesNotMatchException e;
- e.has = first->getClassIdentifier();
- e.required = LISPLIST;
- e.at = 1;
- e.name = stringcpy(name);
- throw e;
- }
- switch (first->getClassIdentifier()) {
- case LISPLIST:{
- LispList *list = (LispList *)first;
- for (int i = 0; i < list->getSize(); i++) {
- LispObject *element = list->getElement(i);
- int ci = element->getClassIdentifier();
- delete element;
- if (ci != LISPSYMBOL) {
- TypeOfArgumentDoesNotMatchException e;
- e.has = ci;
- e.required = LISPSYMBOL;
- e.at = i + 1;
- e.name = stringcpy(name);
- throw e;
- }
- }
- LispProcedure *procedure = new LispProcedure(list->getSize(), list->getSize(), (LispList *)second, env);
- for (int i = 0; i < list->getSize(); i++) {
- LispSymbol *element = (LispSymbol *)list->getElement(i);
- procedure->addNameOfArgument(element->getName());
- delete element;
- }
- return procedure;
- }
- default:{
- if (second->getClassIdentifier() != LISPLIST) {
- TypeOfArgumentDoesNotMatchException e;
- e.has = second->getClassIdentifier();
- e.required = LISPLIST;
- e.at = 2;
- e.name = stringcpy(name);
- throw e;
- }
- return new LispProcedure(0 , 0, (LispList *)second, env);
- }
- }
- }
- LispObject* CondMacro::copy(){
- return new CondMacro(*this);
- }
- LispObject* CondMacro::callMacro(LispObject **args, int argsSize, LispEnvironment *env) throw (NumberOfArgumentsDoesNotMatchException &, TypeOfArgumentDoesNotMatchException &, Exception &){
- for (int i = 0; i < argsSize; i++) {
- if (args[i]->getClassIdentifier() != LISPLIST) {
- TypeOfArgumentDoesNotMatchException e;
- e.at = i + 1;
- e.has = args[i]->getClassIdentifier();
- e.required = LISPLIST;
- e.name = stringcpy("cond");
- throw e;
- } else if (((LispList *)args[i])->getSize() != 2) {
- NumberOfArgumentsDoesNotMatchException e;
- e.has = ((LispList *)args[i])->getSize();
- e.required = 2;
- e.maxRequired = 2;
- e.name = stringcpy("name");
- throw e;
- }
- }
- return evaluate(condToIf(0, (LispList **)args, argsSize), env);
- }
- LispList* CondMacro::condToIf(int i, LispList **args, int argsSize){
- if(i == argsSize - 1){
- LispList *ifList = new LispList();
- IfMacro *ifmacro = new IfMacro();
- ifList->addElement(ifmacro);
- delete ifmacro;
- LispObject *boolean = args[i]->getElement(0);
- ifList->addElement(boolean);
- delete boolean;
- LispObject *first = args[i]->getElement(1);
- ifList->addElement(first);
- delete first;
- LispNil *nil = new LispNil();
- ifList->addElement(nil);
- delete nil;
- return ifList;
- }else {
- LispList *ifList = new LispList();
- IfMacro *ifmacro = new IfMacro();
- ifList->addElement(ifmacro);
- delete ifmacro;
- LispObject *boolean = args[i]->getElement(0);
- ifList->addElement(boolean);
- delete boolean;
- LispObject *first = args[i]->getElement(1);
- ifList->addElement(first);
- delete first;
- ifList->addElement(condToIf(i + 1, args, argsSize));
- return ifList;
- }
- }
- LispObject* IfMacro::copy(){
- return new IfMacro(*this);
- }
- LispObject* IfMacro::callMacro(LispObject **args, int argsSize, LispEnvironment *env) throw (NumberOfArgumentsDoesNotMatchException &, Exception &){
- if (argsSize != 3) {
- NumberOfArgumentsDoesNotMatchException e;
- e.has = argsSize;
- e.maxRequired = 3;
- e.required = 3;
- e.name = stringcpy("if");
- throw e;
- }
- bool boolean;
- LispObject *boolObj = evaluate(args[0], env);
- int ci = boolObj->getClassIdentifier();
- if (ci == LISPBOOLEAN) {
- boolean = ((LispBoolean *) boolObj)->getBool();
- } else if (ci == LISPNIL){
- boolean = false;
- } else {
- boolean = true;
- }
- if (boolean) {
- return evaluate(args[1], env);
- }
- else {
- return evaluate(args[2], env);
- }
- }
- LispObject* QuoteMacro::copy(){
- return new QuoteMacro(*this);
- }
- LispObject* QuoteMacro::callMacro(LispObject **args, int argsSize, LispEnvironment *env) throw (NumberOfArgumentsDoesNotMatchException &, Exception &){
- if (argsSize != 1) {
- NumberOfArgumentsDoesNotMatchException e;
- e.has = argsSize;
- e.maxRequired = 1;
- e.required = 1;
- e.name = stringcpy("quote");
- throw e;
- }
- return ((LispQuote *)args[0])->getItem();
- }
- LispObject* BeginMacro::copy(){
- return new BeginMacro(*this);
- }
- LispObject* BeginMacro::callMacro(LispObject **args, int argsSize, LispEnvironment *env) throw (NumberOfArgumentsDoesNotMatchException &, Exception &){
- if (argsSize == 0){
- NumberOfArgumentsDoesNotMatchException e;
- e.has = 0;
- e.name = stringcpy("begin");
- e.required = 1;
- e.maxRequired = UNLIMITED_ARGUMENTS;
- throw e;
- }
- for (int i = 0; i < argsSize - 1; i++) {
- evaluate(args[i], env);
- }
- return evaluate(args[argsSize - 1], env);
- }
- LispObject* LetMacro::copy(){
- return new LetMacro(*this);
- }
- LispObject* LetMacro::callMacro(LispObject **args, int argsSize, LispEnvironment *env) throw (NumberOfArgumentsDoesNotMatchException &, TypeOfArgumentDoesNotMatchException &, Exception &){
- char *name = stringcpy("let");
- if (argsSize != 2){
- NumberOfArgumentsDoesNotMatchException e;
- e.has = argsSize;
- e.required = 2;
- e.maxRequired = 2;
- e.name = name;
- throw e;
- }
- if (args[0]->getClassIdentifier() != LISPLIST){
- TypeOfArgumentDoesNotMatchException e;
- e.at = 0 + 1;
- e.has = args[0]->getClassIdentifier();
- e.required = LISPLIST;
- e.name = name;
- throw e;
- }
- int itemSize = ((LispList *)args[0])->getSize();
- LispObject **items = new LispObject*[itemSize];
- LispEnvironment *newEnv = new LispEnvironment(env);
- for (int i = 0; i < itemSize; i++) {
- items[i] = ((LispList *)args[0])->getElement(i);
- if (items[i]->getClassIdentifier() != LISPLIST) {
- TypeOfArgumentDoesNotMatchException e;
- e.has = items[i]->getClassIdentifier();
- for (int j = 0; j < i + 1; j++) {
- delete items[j];
- }
- delete[] items;
- e.required = LISPLIST;
- e.name = stringcpy("List");
- e.at = i;
- throw e;
- }
- if (((LispList *)items[i])->getSize() != 2) {
- NumberOfArgumentsDoesNotMatchException e;
- e.has = ((LispList *)items[i])->getSize();
- for (int j = 0; j < i + 1; j++) {
- delete items[j];
- }
- delete[] items;
- e.required = 2;
- e.maxRequired = 2;
- e.name = stringcpy("List");
- throw e;
- }
- LispObject *symbol = ((LispList *)items[i])->getElement(0);
- if (symbol->getClassIdentifier() != LISPSYMBOL) {
- TypeOfArgumentDoesNotMatchException e;
- e.has = items[i]->getClassIdentifier();
- for (int j = 0; j < i + 1; j++) {
- delete items[j];
- }
- delete[] items;
- e.required = LISPSYMBOL;
- e.name = stringcpy("List");
- e.at = 0;
- throw e;
- }
- LispObject *item = evaluate(((LispList *)items[i])->getElement(1), env);
- newEnv->addSymbolValuePair(new LispSymbolValuePair(((LispSymbol *)symbol)->getName(), item));
- }
- return evaluate(args[1], newEnv);
- }
- LispObject* LetAsteriskMacro::copy(){
- return new LetAsteriskMacro(*this);
- }
- LispObject* LetAsteriskMacro::callMacro(LispObject **args, int argsSize, LispEnvironment *env) throw (NumberOfArgumentsDoesNotMatchException &, TypeOfArgumentDoesNotMatchException &, Exception &){
- char *name = stringcpy("let");
- if (argsSize != 2){
- NumberOfArgumentsDoesNotMatchException e;
- e.has = argsSize;
- e.required = 2;
- e.maxRequired = 2;
- e.name = name;
- throw e;
- }
- if (args[0]->getClassIdentifier() != LISPLIST){
- TypeOfArgumentDoesNotMatchException e;
- e.at = 0 + 1;
- e.has = args[0]->getClassIdentifier();
- e.required = LISPLIST;
- e.name = name;
- throw e;
- }
- int itemSize = ((LispList *)args[0])->getSize();
- LispObject **items = new LispObject*[itemSize];
- LispEnvironment *newEnv = new LispEnvironment(env);
- for (int i = 0; i < itemSize; i++) {
- items[i] = ((LispList *)args[0])->getElement(i);
- if (items[i]->getClassIdentifier() != LISPLIST) {
- TypeOfArgumentDoesNotMatchException e;
- e.has = items[i]->getClassIdentifier();
- for (int j = 0; j < i + 1; j++) {
- delete items[j];
- }
- delete[] items;
- e.required = LISPLIST;
- e.name = stringcpy("List");
- e.at = i;
- throw e;
- }
- if (((LispList *)items[i])->getSize() != 2) {
- NumberOfArgumentsDoesNotMatchException e;
- e.has = ((LispList *)items[i])->getSize();
- for (int j = 0; j < i + 1; j++) {
- delete items[j];
- }
- delete[] items;
- e.required = 2;
- e.maxRequired = 2;
- e.name = stringcpy("List");
- throw e;
- }
- LispObject *symbol = ((LispList *)items[i])->getElement(0);
- if (symbol->getClassIdentifier() != LISPSYMBOL) {
- TypeOfArgumentDoesNotMatchException e;
- e.has = items[i]->getClassIdentifier();
- for (int j = 0; j < i + 1; j++) {
- delete items[j];
- }
- delete[] items;
- e.required = LISPSYMBOL;
- e.name = stringcpy("List");
- e.at = 0;
- throw e;
- }
- LispObject *item = evaluate(((LispList *)items[i])->getElement(1), newEnv);
- newEnv->addSymbolValuePair(new LispSymbolValuePair(((LispSymbol *)symbol)->getName(), item));
- }
- return evaluate(args[1], newEnv);
- }
- LispObject* SetExcalMacro::copy(){
- return new SetExcalMacro(*this);
- }
- LispObject* SetExcalMacro::callMacro(LispObject **args, int argsSize, LispEnvironment *env) throw (NumberOfArgumentsDoesNotMatchException &,
- TypeOfArgumentDoesNotMatchException &,
- DefineNotAllowed &,
- Exception &){
- if (argsSize != 2) {
- NumberOfArgumentsDoesNotMatchException e;
- e.has = argsSize;
- e.required = 2;
- e.maxRequired = 2;
- e.name = stringcpy("set!");
- throw e;
- }
- if (args[0]->getClassIdentifier() != LISPSYMBOL) {
- TypeOfArgumentDoesNotMatchException e;
- e.has = args[0]->getClassIdentifier();
- e.required = LISPSYMBOL;
- e.name = stringcpy("set!");
- e.at = 1;
- throw e;
- }
- LispSymbolValuePair **ptrSvp = env->getSymbolValuePairDoublePointer(((LispSymbol *)args[0])->getName());
- LispSymbolValuePair *tmp = *ptrSvp;
- LispObject* evaluated = evaluate(args[1], env);
- if (evaluated->getClassIdentifier() == LISPMACRO){
- delete evaluated;
- DefineNotAllowed e;
- e.syntaxError = true;
- throw e;
- }
- *ptrSvp = new LispSymbolValuePair(((LispSymbol *)args[0])->getName(), evaluated);
- delete tmp;
- return new LispNil();
- }
- LispObject* LoadMacro::copy(){
- return new LoadMacro(*this);
- }
- LispObject* LoadMacro::callMacro(LispObject **args, int argsSize, LispEnvironment *env) throw (NumberOfArgumentsDoesNotMatchException &, TypeOfArgumentDoesNotMatchException &, Exception &){
- if (argsSize != 1) {
- NumberOfArgumentsDoesNotMatchException e;
- e.has = argsSize;
- e.required = 1;
- e.maxRequired = 1;
- e.name = stringcpy("load");
- throw e;
- }
- if (args[0]->getClassIdentifier() != LISPSTRING) {
- TypeOfArgumentDoesNotMatchException e;
- e.has = args[0]->getClassIdentifier();
- e.name = stringcpy("load");
- e.required = LISPSTRING;
- e.at = 1;
- throw e;
- }
- char *expression = loadFile(((LispString *)args[0])->getString());
- if(!run(expression, env)){
- std::cout << "Exit by external file" << std::endl;
- exit(0);
- }
- return new LispNil();
- }