JSValue *evaluate(Scope *scope) {
        JSValue *lhsValue = lhs->evaluate(scope);

        if (lhsValue->jsType() == JSExternalFunctionType) {
            vector<JSValue *> args;
            for (JSExpression *x: rhs) {
                args.push_back(x->evaluate(scope));
            }

            JSExternalFunctionImplementation implementation = ((JSExternalFunction *) lhsValue)->getImplementation();

            return implementation(args);
        }
        else if (lhsValue->jsType() == JSFunctionType) {
            JSFunction *functionValue = (JSFunction *) lhsValue;

            Scope *newScope = new Scope(scope);

            for (int i = 0; i < functionValue->getArgNames().size(); i++) {
                newScope->declareValue(functionValue->getArgNames()[i], rhs[i]->evaluate(scope));
            }

            JSValue *result = interpretBlock(functionValue->getStatements(), newScope);
            return (result == nullptr) ? jsUndefined : result;
        }
        else {
            cout << "trying to call " << lhsValue->toString() << ", which can't be called :(" << endl;
            exit(123);
        }
    }