예제 #1
0
 public static JymlAST.Cons Eval(JymlAST.Cons exp, JymlEnvironment env)
 {
     if (exp != null)
     {
         if (Parser.IsSelfEvaluating(exp))
         {
             return(new JymlAST.Cons(exp.car, Eval(exp.cdr as JymlAST.Cons, env)));
         }
         else if (Parser.IsAssignment(exp))
         {
             return(EvalAssignment(exp, env));
         }
         else if (Parser.IsDefinition(exp))
         {
             return(EvalDefinition(exp, env));
         }
         else if (Parser.IsIf(exp))
         {
             return(EvalIf(exp, env));
         }
         else if (Parser.IsLambda(exp))
         {
             return(MakeLambda(Parser.GetLambdaParameters(exp), Parser.GetLambdaBody(exp), env));
         }
         else if (Parser.IsBegin(exp))
         {
             return(EvalSequence(exp.cdr as JymlAST.Cons, env));
         }
         else if (exp.car is JymlAST.Cons subexp)
         {
             return(new JymlAST.Cons(Eval(subexp, env), Eval(exp.cdr as JymlAST.Cons, env)));
         }
         else
         {
             if (exp.car is string proc)
             {
                 JymlEnvironment.Restraint restraint = env[proc];
                 if (restraint != null)
                 {
                     if (restraint.Value is Procedures || restraint.Value is PrimitiveProcedure)
                     {
                         return(Apply(proc, ListOfValues(exp.cdr as JymlAST.Cons, env), env));
                     }
                     else
                     {
                         return(new JymlAST.Cons(restraint.Value, Eval(exp.cdr as JymlAST.Cons, env)));
                     }
                 }
                 else
                 {
                     if (Parser.IsVariable(exp))
                     {
                         throw new Exception($"变量 {exp.car} 未定义。");
                     }
                     else
                     {
                         throw new Exception($"无效的语法:{exp}");
                     }
                 }
             }
             else if (exp.car is JymlAST.Cons cons)
             {
                 return(Apply(cons, ListOfValues(exp.cdr as JymlAST.Cons, env), env));
             }
             else
             {
                 throw new Exception($"无效的过程调用:{exp}");
             }
         }
     }
     else
     {
         return(null);
     }
 }
예제 #2
0
        /*
         * (define (eval-definition exp env)
         *      (define-variable!   (definition-variable exp)
         *                          (eval (definition-value exp) env)
         *                          env))
         */
        private static JymlAST.Cons EvalDefinition(JymlAST.Cons exp, JymlEnvironment env)
        {
            /*
             * (define (definition-variable exp)
             *      (if [symbol? [mcar [mcdr exp]]]
             *          [mcar [mcdr exp]]
             *          [mcar [mcar [mcdr exp]]]))
             */
            string defineVariable(JymlAST.Cons c) =>
            Parser.IsVariable(c.cdr as JymlAST.Cons) ? (c.cdr as JymlAST.Cons).car as string                            // 普通变量或 lambda 变量
                                                         : ((c.cdr as JymlAST.Cons).car as JymlAST.Cons).car as string; // 过程定义

            /*
             * (define (definition-value exp)
             *      (if [symbol? [mcar [mcdr exp]]]
             *          [mcar [mcdr [mcdr exp]]]
             *          (make-lambda    [mcdr [mcar [mcdr exp]]]    ; formal parameters
             *                          [mcdr [mcdr exp]])))        ; body
             */
            JymlType defineValue(JymlAST.Cons c)
            {
                if (Parser.IsVariable(c.cdr as JymlAST.Cons))
                {
                    if (((c.cdr as JymlAST.Cons).cdr as JymlAST.Cons).car is string atom)
                    {
                        return(JymlType.CreateType(atom));  // 普通变量或 lambda 变量
                    }
                    else if (((c.cdr as JymlAST.Cons).cdr as JymlAST.Cons).car is JymlAST.Cons cons)
                    {
                        return(JymlType.CreateType(Eval(cons, env).car));    // 返回一个 value 的子表达式(过程调用)
                    }
                    else
                    {
                        throw new Exception($"define 表达式 {exp} 的 value 部分只能是一个原子值或一个返回原子值的过程调用。");
                    }
                }
                else
                {
                    return(new Procedures(Parser.GetProcedureName(exp), (JymlAST.Cons)Parser.GetLambdaParameters(exp), Parser.GetLambdaBody(exp), env));   // 过程定义
                }
            }

            env.DefineVariable(defineVariable(exp), defineValue(exp));
            return(null);
        }