예제 #1
0
 public LittleLisp()
 {
     _nil = MakeSpecial(Tnil);
     _dot = MakeSpecial(Tdot);
     _cparen = MakeSpecial(Tcparen);
     _true = MakeSpecial(Ttrue);
     _symbols = _nil;
     _rootenv = MakeEnv(_nil, null);
     DefineConstants(_rootenv);
     DefinePrimitives(_rootenv);
 }
예제 #2
0
        public Obj Eval(string s, Obj env)
        {
            env = env ?? _rootenv;
            _currentSource = s;
            _currentPos = 0;

            Obj expr = _nil;
            while (_currentPos < _currentSource.Length)
            {
                expr = Read();
                if (expr == null)
                    return null;
                if (expr == _cparen)
                    Error("Stray close parenthesis");
                if (expr == _dot)
                    Error("Stray dot");
                expr = Eval(env, expr);
            }
            return expr;
        }
예제 #3
0
 public void Repl(Obj env)
 {
     env = env ?? _rootenv;
     while (true)
     {
         try
         {
             Console.Write(": ");
             string input = Console.ReadLine();
             while (OpenBrackets(input) > 0)
             {
                 Console.Write("> ");
                 input += "\n" + Console.ReadLine();
             }
             Print(Eval(input, env));
             Print("\n");
         }
         catch
         { }
     }
 }
예제 #4
0
 // (+ <integer> ...)
 private Obj PrimPlus(Obj env, Obj list)
 {
     int sum = 0;
     for (Obj args = EvalList(env, list); args != _nil; args = args.Rest)
     {
         if (args.First.Type != Tint)
             Error("+ takes only numbers");
         sum += args.First.Value;
     }
     return MakeInt(sum);
 }
예제 #5
0
 // (< <integer> <integer>)
 private Obj PrimNumLt(Obj env, Obj list)
 {
     Obj args = EvalList(env, list);
     if (ListLength(args) != 2)
         Error("malformed <");
     Obj x = args.First;
     Obj y = args.Rest.First;
     if (x.Type != Tint || y.Type != Tint)
         Error("< takes only numbers");
     return x.Value < y.Value ? _true : _nil;
 }
예제 #6
0
 // Expands the given macro application form.
 private Obj MacroExpand(Obj env, Obj obj)
 {
     if (obj.Type != Tcell || obj.First.Type != Tsymbol)
         return obj;
     // Lookup the macro definition, if any
     Obj bind = Find(env, obj.First);
     if (bind == null || bind.Rest.Type != Tmacro)
         return obj;
     Obj macro = bind.Rest;
     Obj args = obj.Rest;
     return ApplyFunction(env, macro, args);
 }
예제 #7
0
 // Returns a newly created environment frame.
 private Obj PushEnv(Obj env, Obj vars, Obj values)
 {
     Obj map = _nil;
     for (; vars.Type == Tcell; vars = vars.Rest, values = values.Rest)
     {
         if (values.Type != Tcell)
             Error("Cannot apply function: number of argument does not match");
         Obj sym = vars.First;
         Obj val = values.First;
         map = Acons(sym, val, map);
     }
     if (vars != _nil)
         map = Acons(vars, values, map);
     return MakeEnv(map, env);
 }
예제 #8
0
 // Prints the given object.
 private void Print(Obj obj)
 {
     if (obj.Type == Tint)
         Print(obj.Value.ToString());
     else if (obj.Type == Tcell)
     {
         Print("(");
         while (true)
         {
             Print(obj.First);
             if (obj.Rest == _nil)
                 break;
             if (obj.Rest.Type != Tcell)
             {
                 Print(" . ");
                 Print(obj.Rest);
                 break;
             }
             Print(" ");
             obj = obj.Rest;
         }
         Print(")");
     }
     else if (obj.Type == Tsymbol)
         Print(obj.Name);
     else if (obj.Type == Tprimitive)
         Print("<primitive>");
     else if (obj.Type == Tfunction)
         Print("<function>");
     else if (obj.Type == Tmacro)
         Print("<macro>");
     else if (obj.Type == Tnil)
         Print("()");
     else if (obj.Type == Ttrue)
         Print("t");
     else
         Error(string.Format("Bug: print: Unknown tag type: {0}", obj.Type));
 }
예제 #9
0
 // (setq <symbol> expr)
 private Obj PrimSetq(Obj env, Obj list)
 {
     if (ListLength(list) != 2 || list.First.Type != Tsymbol)
         Error("Malformed setq");
     Obj bind = Find(env, list.First);
     if (bind == null)
         Error(string.Format("Unbound variable {0}", list.First.Name));
     return bind.Rest = Eval(env, list.Rest.First);
 }
예제 #10
0
 // (rest <cell>) (cdr <cell>)
 private Obj PrimRest(Obj env, Obj list)
 {
     Obj args = EvalList(env, list);
     if (args.First.Type != Tcell || args.Rest != _nil)
         Error("Malformed rest");
     return args.First.Rest;
 }
예제 #11
0
 // (join expr expr) (cons expr expr)
 private Obj PrimJoin(Obj env, Obj list)
 {
     if (ListLength(list) != 2)
         Error("Malformed join");
     Obj cell = EvalList(env, list);
     cell.Rest = cell.Rest.First;
     return cell;
 }
예제 #12
0
        // (if expr expr expr ...)
        private Obj PrimIf(Obj env, Obj list)
        {
            if (ListLength(list) < 2)
                Error("Malformed if");
            if (Eval(env, list.First) != _nil)
                return Eval(env, list.Rest.First);

            Obj els = list.Rest.Rest;
            return els == _nil ? _nil : Progn(env, els);
        }
예제 #13
0
 // (gensym)
 private Obj PrimGenSym(Obj env, Obj list)
 {
     return MakeSymbol("G_" + _nextSymbol++);
 }
예제 #14
0
 // (eq expr expr)
 private Obj PrimEq(Obj env, Obj list)
 {
     if (ListLength(list) != 2)
         Error("Malformed eq");
     Obj values = EvalList(env, list);
     return values.First == values.Rest.First ? _true : _nil;
 }
예제 #15
0
 // (defun <symbol> (<symbol> ...) expr ...)
 private Obj PrimDefun(Obj env, Obj list)
 {
     return HandleDefun(env, list, Tfunction);
 }
예제 #16
0
 // (defmacro <symbol> (<symbol> ...) expr ...)
 private Obj PrimDefMacro(Obj env, Obj list)
 {
     return HandleDefun(env, list, Tmacro);
 }
예제 #17
0
 // (define <symbol> expr)
 private Obj PrimDefine(Obj env, Obj list)
 {
     if (ListLength(list) != 2 || list.First.Type != Tsymbol)
         Error("Malformed define");
     Obj sym = list.First;
     Obj value = Eval(env, list.Rest.First);
     AddVariable(env, sym, value);
     return value;
 }
예제 #18
0
 // (println expr)
 private Obj PrimPrintln(Obj env, Obj list)
 {
     Print(Eval(env, list.First));
     Print("\n");
     return _nil;
 }
예제 #19
0
 // 'expr
 private Obj PrimQuote(Obj env, Obj list)
 {
     if (ListLength(list) != 1)
         Error("Malformed quote");
     return list.First;
 }
예제 #20
0
 // (lambda (<symbol> ...) expr ...)
 private Obj PrimLambda(Obj env, Obj list)
 {
     return HandleFunction(env, list, Tfunction);
 }
예제 #21
0
 // (setcar <cell> expr) (setfirst <cell> expr)
 private Obj PrimSetFirst(Obj env, Obj list)
 {
     Obj args = EvalList(env, list);
     if (ListLength(args) != 2 || args.First.Type != Tcell)
         Error("Malformed setcar");
     args.First.First = args.Rest.First;
     return args.First;
 }
예제 #22
0
 // (macroexpand expr)
 private Obj PrimMacroExpand(Obj env, Obj list)
 {
     if (ListLength(list) != 1)
         Error("Malformed macroexpand");
     return MacroExpand(env, list.First);
 }
예제 #23
0
        // (while cond expr ...)
        private Obj PrimWhile(Obj env, Obj list)
        {
            if (ListLength(list) < 2)
                Error("Malformed while");
            while (Eval(env, list.First) != _nil)
                EvalList(env, list.Rest);

            return _nil;
        }
예제 #24
0
 // (- <integer> ...)
 private Obj PrimMinus(Obj env, Obj list)
 {
     Obj args = EvalList(env, list);
     for (Obj p = args; p != _nil; p = p.Rest)
         if (p.First.Type != Tint)
             Error("- takes only numbers");
     int r = args.First.Value;
     if (args.Rest == _nil)
         return MakeInt(-r);
     for (Obj p = args.Rest; p != _nil; p = p.Rest)
         r -= p.First.Value;
     return MakeInt(r);
 }
예제 #25
0
 // Evaluates the list elements from head and returns the last return value.
 private Obj Progn(Obj env, Obj list)
 {
     Obj r = null;
     for (Obj lp = list; lp != _nil; lp = lp.Rest)
         r = Eval(env, lp.First);
     return r;
 }
예제 #26
0
 // Destructively reverses the given list.
 private Obj Reverse(Obj p)
 {
     Obj ret = _nil;
     while (p != _nil)
     {
         Obj head = p;
         p = p.Rest;
         head.Rest = ret;
         ret = head;
     }
     return ret;
 }
예제 #27
0
 private bool IsList(Obj obj)
 {
     return obj == _nil || obj.Type == Tcell;
 }
예제 #28
0
 private int ListLength(Obj list)
 {
     int len = 0;
     for (; list.Type == Tcell; list = list.Rest)
         len++;
     return list == _nil ? len : -1;
 }
예제 #29
0
 // (= <integer> <integer>)
 private Obj PrimNumEq(Obj env, Obj list)
 {
     if (ListLength(list) != 2)
         Error("Malformed =");
     Obj values = EvalList(env, list);
     Obj x = values.First;
     Obj y = values.Rest.First;
     if (x.Type != Tint || y.Type != Tint)
         Error("= only takes numbers");
     return x.Value == y.Value ? _true : _nil;
 }
예제 #30
0
 // May create a new symbol. If there's a symbol with the same name, it will not create a new symbol
 // but return the existing one.
 private Obj Intern(string name)
 {
     for (Obj p = _symbols; p != _nil; p = p.Rest)
         if (name == p.First.Name)
             return p.First;
     Obj sym = MakeSymbol(name);
     _symbols = Join(sym, _symbols);
     return sym;
 }