Exemple #1
0
        // Name changed from the guide to highlight that the outcome is complicated.
        static JKLVal Quasiquote(JKLVal ast)
        {
            if (!is_pair(ast))
            {
                // Case 1.
                // If is_pair of ast is false: return a new list containing: a symbol named "quote" and ast.
                JKLList qList = new JKLList();

                qList.Add(new JKLSym("quote"));
                qList.Add(ast);

                //qList.Conj(new JKLSym("quote"), ast);
                return(qList);
            }
            else
            {
                JKLSequence astSeq = (JKLSequence)ast;
                JKLVal      a0     = astSeq[0];

                // Case 2:  if the first element of ast is a symbol named "unquote": return the second element of ast.
                if (a0 is JKLSym a0Sym && a0Sym.getName() == "unquote")
                {
                    // (qq (uq form)) -> form
                    return(astSeq[1]);
                }
Exemple #2
0
 public JKLFunc(JKLVal ast, Env e, JKLSequence fparams, Func <JKLList, JKLVal> fn)
 {
     this.ast     = ast;
     this.env     = e;
     this.fparams = fparams;
     this.fn      = fn;
     IsCore       = false;
 }
Exemple #3
0
        // Given a sequence of symbols (binds) and a list of expressions, work through the
        // sequences, setting each bind in turn to the value of its corresponding expression.
        // The primary application is setting function arguments (binds) to their values (expressions).
        // If one of the binds is the Var args character ('&') the next bind is associated with
        // all of the remaining exprs. Trapped errors include non-symbols being used as binds
        // or cases where the binds and expr sequences are of incompatible lengths.
        public Env(Env outer, JKLSequence binds, JKLSequence exprs)
        {
            // A key-JKLVal dictionary.
            data = new Dictionary <string, JKLVal>();

            // The scope we are created in. Null is taken to mean the outermost REPL's env.
            this.outer = outer;
            int bindsProcessed = 0;

            //  (def f (fn (a & b) (list a b))) -- okay
            // Bind (set) each element (symbol) to the respective elements of the exprs list.
            for (bindsProcessed = 0; bindsProcessed < binds.Count(); bindsProcessed++)
            {
                if (binds[bindsProcessed] == jklVarArgsChar)
                {
                    // E.g. (fn* f (a1 a2 & restArgs) (list a1 a2 restargs )) called with (f 1 2 3 4)
                    if (bindsProcessed == binds.Count() - 1)
                    {
                        // jklVarArgsChar isn't followed by the name of the varargs parameter.
                        throw new JKLEvalError("Expected symbol after & in arg list");
                        // If there are multiple symbols after '&' all but the first will be trapped as
                        // unbound symbols later on.
                    }
                    if (binds[bindsProcessed + 1] is JKLSym symbol)
                    {
                        // Bind the rest of the expressions to the symbol following the varargs char.
                        Set(symbol, exprs.GetRange(bindsProcessed, exprs.Count()));
                        return;
                    }
                    else
                    {
                        // Not sure if this can heppen but just in case.
                        throw new JKLEvalError("Expected symbol after & but got '" + binds[bindsProcessed + 1].ToString(true));
                    }
                    //
                }
                else if (binds[bindsProcessed] is JKLSym symbol)
                {
                    // Bind an expression to a binding symbol.
                    if (bindsProcessed >= exprs.Count())
                    {
                        throw new JKLEvalError("Incorrect number of arguments " + exprs.Count());
                    }
                    Set(symbol, exprs[bindsProcessed]);
                }
                else
                {
                    throw new JKLEvalError("expected symbol to bind but got '" + binds[bindsProcessed].ToString(true) + '"');
                }
            }
            if (bindsProcessed < exprs.Count())
            {
                // We ran out of bindings although there are expressions remaining.
                throw new JKLEvalError(exprs.ToString(true) + " - more expressions (" + exprs.Count() + ") than bindings: " + bindsProcessed);
            }
        }
Exemple #4
0
 public JKLFunc(JKLVal ast, Env e, JKLSequence fparams, Func <JKLList, JKLVal> fn, bool isMacro, JKLVal meta)
 {
     this.ast     = ast;
     this.env     = e;
     this.fparams = fparams;
     this.fn      = fn;
     this.isMacro = isMacro;
     this.meta    = meta;
     IsCore       = false;
 }