From 49ba52239afa0e6ab295add695a7443633748cfc Mon Sep 17 00:00:00 2001 From: jsdelfino Date: Sun, 27 Sep 2009 20:03:58 +0000 Subject: Strawman implementation of a mini script evaluation library, which can be used for simple test case components without requiring integration with bigger and more complex 3rd party script engines like Ruby or Python. That way the core test cases should work without requiring the more complex Python or Ruby extensions to work. git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@819393 13f79535-47bb-0310-9956-ffa450edef68 --- cpp/sca/modules/eval/eval.hpp | 383 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 383 insertions(+) create mode 100644 cpp/sca/modules/eval/eval.hpp (limited to 'cpp/sca/modules/eval/eval.hpp') diff --git a/cpp/sca/modules/eval/eval.hpp b/cpp/sca/modules/eval/eval.hpp new file mode 100644 index 0000000000..23e9554aa8 --- /dev/null +++ b/cpp/sca/modules/eval/eval.hpp @@ -0,0 +1,383 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/* $Rev$ $Date$ */ + +#ifndef tuscany_eval_eval_hpp +#define tuscany_eval_eval_hpp + +/** + * Script evaluator core evaluation logic. + */ + +#include +#include "list.hpp" +#include "value.hpp" +#include "primitive.hpp" +#include "read.hpp" +#include "environment.hpp" + +namespace tuscany +{ + +const value compoundProcedureSymbol("compound-procedure"); +const value procedureSymbol("procedure"); +const value beginSymbol("begin"); +const value condSymbol("cond"); +const value elseSymbol("else"); +const value ifSymbol("if"); + +const bool isBegin(const value& exp) { + return isTaggedList(exp, beginSymbol); +} + +const list beginActions(const value& exp) { + return cdr((list )exp); +} + +const bool isLambda(const value& exp) { + return isTaggedList(exp, lambdaSymbol); +} + +const list lambdaParameters(const value& exp) { + return car(cdr((list )exp)); +} + +static list lambdaBody(const value& exp) { + return cdr(cdr((list )exp)); +} + +const value makeProcedure(const list& parameters, const value& body, const Env& env) { + return value(makeList(procedureSymbol, value(parameters), body, value(env))); +} + +const bool isApplication(const value& exp) { + return isList(exp); +} + +const value operat(const value& exp) { + return car((list )exp); +} + +const list operands(const value& exp) { + return cdr((list )exp); +} + +const bool isCompoundProcedure(const value& procedure) { + return isTaggedList(procedure, procedureSymbol); +} + +const list procedureParameters(const value& exp) { + return car(cdr((list )exp)); +} + +const value procedureBody(const value& exp) { + return car(cdr(cdr((list )exp))); +} + +const Env procedureEnvironment(const value& exp) { + return (Env)car(cdr(cdr(cdr((list )exp)))); +} + +const bool isLastExp(const list& seq) { + return cdr(seq) == list (); +} + +const value firstExp(const list& seq) { + return car(seq); +} + +const value makeBegin(const list seq) { + return value(cons(beginSymbol, seq)); +} + +const value sequenceToExp(const list exps) { + if(exps == list ()) + return value(list()); + if(isLastExp(exps)) + return firstExp(exps); + return makeBegin(exps); +} + +const list condClauses(const value& exp) { + return cdr((list )exp); +} + +const value condPredicate(const value& clause) { + return car((list )clause); +} + +const list condActions(const value& clause) { + return cdr((list )clause); +} + +const value ifPredicate(const value& exp) { + return car(cdr((list )exp)); +} + +const value ifConsequent(const value& exp) { + return car(cdr(cdr((list )exp))); +} + +const value ifAlternative(const value& exp) { + if(cdr(cdr(cdr((list )exp))) != list ()) + return car(cdr(cdr(cdr((list )exp)))); + return value(false); +} + +const bool isCond(const value& exp) { + return isTaggedList(exp, condSymbol); +} + +const bool isCondElseClause(const value& clause) { + return condPredicate(clause) == elseSymbol; +} + +const bool isIf(const value& exp) { + return isTaggedList(exp, ifSymbol); +} + +const value makeIf(value predicate, value consequent, value alternative) { + return value(makeList(ifSymbol, predicate, consequent, alternative)); +} + +const value expandClauses(const list& clauses) { + if(clauses == list ()) + return value(false); + const value first = car(clauses); + const list rest = cdr(clauses); + if(isCondElseClause(first)) { + if(rest == list ()) + return sequenceToExp(condActions(first)); + std::cout << "else clause isn't last " << clauses << "\n"; + return value(); + } + return makeIf(condPredicate(first), sequenceToExp(condActions(first)), expandClauses(rest)); +} + +value condToIf(const value& exp) { + return expandClauses(condClauses(exp)); +} + +const lambda analyze(const value exp); + +struct evalUndefinedLambda { + evalUndefinedLambda() { + } + + const value operator()(Env& env) const { + return value(); + } +}; + +struct evalSelfEvaluatingLambda { + const value exp; + evalSelfEvaluatingLambda(const value& exp) : exp(exp) { + } + const value operator()(Env& env) const { + return exp; + } +}; + +const lambda analyzeSelfEvaluating(value exp) { + return lambda(evalSelfEvaluatingLambda(exp)); +} + +struct evalQuotedLambda { + const value qval; + evalQuotedLambda(const value& qval) : qval(qval) { + } + const value operator()(Env& env) const { + return qval; + } +}; + +const lambda analyzeQuoted(const value& exp) { + return lambda(evalQuotedLambda(textOfQuotation(exp))); +} + +struct evalVariableLambda { + const value var; + evalVariableLambda(const value& var) : var(var) { + } + const value operator()(Env& env) const { + return lookupVariableValue(var, env); + } +}; + +const lambda analyzeVariable(const value& exp) { + return lambda(evalVariableLambda(exp)); +} + +struct evalDefinitionLambda { + const value var; + const lambda vproc; + evalDefinitionLambda(const value& var, const lambda& vproc) : var(var), vproc(vproc) { + } + const value operator()(Env& env) const { + env = defineVariable(var, vproc(env), env); + return var; + } +}; + +const lambda analyzeDefinition(const value& exp) { + return lambda(evalDefinitionLambda(definitionVariable(exp), analyze(definitionValue(exp)))); +} + +struct evalIfLambda { + const lambda pproc; + const lambda cproc; + const lambda aproc; + evalIfLambda(const lambda pproc, const lambda& cproc, const lambda& aproc) : + pproc(pproc), cproc(cproc), aproc(aproc) { + } + const value operator()(Env& env) const { + if(pproc(env)) + return cproc(env); + return aproc(env); + } +}; + +const lambda analyzeIf(const value& exp) { + const lambda pproc = analyze(ifPredicate(exp)); + const lambda cproc = analyze(ifConsequent(exp)); + const lambda aproc = analyze(ifAlternative(exp)); + return lambda(evalIfLambda(pproc, cproc, aproc)); +} + +struct evalSequenceLambda { + const lambda proc1; + const lambda proc2; + evalSequenceLambda(const lambda& proc1, const lambda& proc2) : + proc1(proc1), proc2(proc2) { + } + const value operator()(Env& env) const { + proc1(env); + return proc2(env); + } +}; + +const lambda analyzeSequenceSequentially(const lambda& proc1, const lambda& proc2) { + return lambda(evalSequenceLambda(proc1, proc2)); +} + +const lambda analyzeSequenceLoop(const lambda& firstProc, const list >& restProcs) { + if(restProcs == list >()) + return firstProc; + return analyzeSequenceLoop(analyzeSequenceSequentially(firstProc, car(restProcs)), cdr(restProcs)); +} + +const lambda analyzeSequence(const list& exps) { + lambda(value exp)> a(analyze); + const list > procs = map(a, exps); + if(procs == list >()) { + std::cout << "Empty sequence" << "\n"; + return lambda(evalUndefinedLambda()); + } + return analyzeSequenceLoop(car(procs), cdr(procs)); +} + +struct lambdaLambda { + const list vars; + const lambda bproc; + lambdaLambda(const list vars, const lambda& bproc) + : vars(vars), bproc(bproc) { + } + + const value operator()(Env& env) const { + return makeProcedure(vars, value(bproc), env); + } +}; + +const lambda analyzeLambda(const value& exp) { + const list vars = lambdaParameters(exp); + const lambda bproc = analyzeSequence(lambdaBody(exp)); + return lambda(lambdaLambda(vars, bproc)); +} + +const value executeApplication(const value& proc, const list& args) { + if(isPrimitiveProcedure(proc)) { + list ncargs = args; + return applyPrimitiveProcedure(proc, ncargs); + } + if(isCompoundProcedure(proc)) { + lambda bproc(procedureBody(proc)); + Env env = extendEnvironment(procedureParameters(proc), args, procedureEnvironment(proc)); + return bproc(env); + } + std::cout << "Unknown procedure type " << proc << "\n"; + return value(); +} + +struct evalApplicationArgLambda { + Env& env; + evalApplicationArgLambda(Env& env) : env(env) { + } + const value operator()(const lambda& aproc) const { + return aproc(env); + } +}; + +struct evalApplicationLambda { + const lambda fproc; + const list > aprocs; + evalApplicationLambda(const lambda& fproc, const list >& aprocs) : + fproc(fproc), aprocs(aprocs) { + } + const value operator()(Env& env) const { + return executeApplication(fproc(env), map(lambda)>(evalApplicationArgLambda(env)), aprocs)); + } +}; + +const lambda analyzeApplication(const value& exp) { + const lambda fproc = analyze(operat(exp)); + lambda(value exp)> a(analyze); + const list > aprocs = map(a, operands(exp)); + return lambda(evalApplicationLambda(fproc, aprocs)); +} + +const lambda analyze(const value exp) { + if(isSelfEvaluating(exp)) + return analyzeSelfEvaluating(exp); + if(isQuoted(exp)) + return analyzeQuoted(exp); + if(isDefinition(exp)) + return analyzeDefinition(exp); + if(isIf(exp)) + return analyzeIf(exp); + if(isBegin(exp)) + return analyzeSequence(beginActions(exp)); + if(isCond(exp)) + return analyze(condToIf(exp)); + if(isLambda(exp)) + return analyzeLambda(exp); + if(isVariable(exp)) + return analyzeVariable(exp); + if(isApplication(exp)) + return analyzeApplication(exp); + std::cout << "Unknown expression type " << exp << "\n"; + return lambda(evalUndefinedLambda()); +} + + const value eval(const value& exp, Env& env) { + return analyze(exp)(env); +} + +} +#endif /* tuscany_eval_eval_hpp */ -- cgit v1.2.3