Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon.

Pages: 1-

Show us your Lisp implementations

Name: Anonymous 2011-08-13 6:37

Toy implementations are fine, but (loop (print (eval (read)))) doesn't count!

Name: Anonymous 2011-08-13 7:27

>>1
OK, you start.

Name: Anonymous 2011-08-13 10:35

I'm >>2 and I have a lisp implementation at hand but I don't want to show it unless you show yours first...


yeah right

Name: Anonymous 2011-08-13 13:15

>>3
you show me yours ill show you mine

Name: Anonymous 2011-08-13 14:11

(loop (print (eval (read))))

/thread

Name: Anonymous 2011-08-13 16:54

>>3
I'm >>1 and I think more than one person here has made a toy Lisp implementation

Name: gay ugly implementation 2011-08-13 17:11

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>

enum type {CONS, ATOM, FUNC, LAMBDA};

typedef struct{
  enum type type;
} object;

typedef struct {
  enum type type;
  char *name;
} atom_object;

typedef struct {
  enum type type;
  object *car;
  object *cdr;
} cons_object;

typedef struct {
  enum type type;
  object* (*fn)(object*,object*);
} func_object;

typedef struct {
  enum type type;
  object* args;
  object* sexp;
} lambda_object;

#define car(X)           (((cons_object *) (X))->car)
#define cdr(X)           (((cons_object *) (X))->cdr)

char *name(object *o){
  if(o->type != ATOM) exit(1);
  return ((atom_object*)o)->name;
}

object *atom (char *n) {
  atom_object *ptr = (atom_object *) malloc (sizeof (atom_object));
  ptr->type = ATOM;
  char *name;
  name = malloc(strlen(n) + 1);
  strcpy(name, n);
  ptr->name = name;
  return (object *) ptr;
}

object *cons (object *first, object *second) {
  cons_object *ptr = (cons_object *) malloc (sizeof (cons_object));
  ptr->type = CONS;
  ptr->car = first;
  ptr->cdr = second;
  return (object *) ptr;
}

object *func (object* (*fn)(object*, object*)) {
  func_object *ptr = (func_object *) malloc (sizeof (func_object));
  ptr->type = FUNC;
  ptr->fn = fn;
  return (object *) ptr;
}

void append (object *list, object *obj) {
  object *ptr;
  for (ptr = list; cdr(ptr) != NULL; ptr = cdr(ptr));
  cdr(ptr) = cons(obj, NULL);
}

object *lambda (object *args, object *sexp) {
  lambda_object *ptr = (lambda_object *) malloc (sizeof (lambda_object));
  ptr->type = LAMBDA;
  ptr->args = args;
  ptr->sexp = sexp;
  return (object *) ptr;
}

object *tee,*nil;

//
//
//
//

object *eval (object *sexp, object *env);

object *fn_car (object *args, object *env) {
  return car(car(args));
}

object *fn_cdr (object *args, object *env) {
  return cdr(car(args));
}

object *fn_quote (object *args, object *env) {
  return car(args);
}

object *fn_cons (object *args, object *env) {
  object *list = cons(car(args),NULL);
  args = car(cdr(args));

  while (args != NULL && args->type == CONS){
    append(list,car(args));
    args = cdr(args);
  }

  return list;
}

object *fn_equal (object *args, object *env) {
  object *first = car(args);
  object *second = car(cdr(args));
  if(strcmp(name(first),name(second)) == 0)
    return tee;
  else
    return nil;
}

object *fn_atom (object *args, object *env) {
  if(car(args)->type == ATOM)
    return tee;
  else
    return nil;
}

object *fn_cond (object *args, object *env) {

  while (args != NULL && args->type == CONS){
    object *list = car(args);
    object *pred = nil;

    if (car(list) != nil)
      pred = eval(car(list), env);

    object *ret = car(cdr(list));

    if(pred != nil)
      return eval(ret,env);

    args = cdr(args);
  }

  return nil;
}

object *interleave (object *c1, object *c2) {
  object *list = cons(cons(car(c1),cons(car(c2),NULL)),NULL);
  c1 = cdr(c1);
  c2 = cdr(c2);

  while (c1 != NULL && c1->type == CONS){
    append(list,cons(car(c1),cons(car(c2),NULL)));
    c1 = cdr(c1);
    c2 = cdr(c2);
  }

  return list;
}

object *replace_atom (object *sexp, object *with) {

  if(sexp->type == CONS){

    object *list = cons(replace_atom(car(sexp), with),NULL);
    sexp = cdr(sexp);

    while (sexp != NULL && sexp->type == CONS){
      append(list,replace_atom(car(sexp), with));
      sexp = cdr(sexp);
    }

    return list;
  }else{
    object* tmp = with;

    while (tmp != NULL && tmp->type == CONS) {
      object *item = car(tmp);
      object *atom = car(item);
      object *replacement = car(cdr(item));

      if(strcmp(name(atom),name(sexp)) == 0)
    return replacement;

      tmp = cdr(tmp);
    }

    return sexp;
  }
}

object *fn_lambda (object *args, object *env) {
  object *lambda = car(args);
  args = cdr(args);

  object *list = interleave((((lambda_object *) (lambda))->args),args);
  object* sexp = replace_atom((((lambda_object *) (lambda))->sexp),list);
  return eval(sexp,env);
}

object *fn_label (object *args, object *env) {
  append(env,cons(atom(name(car(args))),cons(car(cdr(args)),NULL)));
  return tee;
}

object* lookup(char* n, object *env){
  object *tmp = env;

  while (tmp != NULL && tmp->type == CONS) {
    object *item = car(tmp);
    object *nm = car(item);
    object *val = car(cdr(item));

    if(strcmp(name(nm),n) == 0)
      return val;
    tmp = cdr(tmp);
  }
  return NULL;
}

object* init_env(){
  object *env = cons(cons(atom("QUOTE"),cons(func(&fn_quote),NULL)),NULL);
  append(env,cons(atom("CAR"),cons(func(&fn_car),NULL)));
  append(env,cons(atom("CDR"),cons(func(&fn_cdr),NULL)));
  append(env,cons(atom("CONS"),cons(func(&fn_cons),NULL)));
  append(env,cons(atom("EQUAL"),cons(func(&fn_equal),NULL)));
  append(env,cons(atom("ATOM"),cons(func(&fn_atom),NULL)));
  append(env,cons(atom("COND"),cons(func(&fn_cond),NULL)));
  append(env,cons(atom("LAMBDA"),cons(func(&fn_lambda),NULL)));
  append(env,cons(atom("LABEL"),cons(func(&fn_label),NULL)));

  tee = atom("#T");
  nil = cons(NULL,NULL);

  return env;
}

object *eval_fn (object *sexp, object *env){
  object *symbol = car(sexp);
  object *args = cdr(sexp);

  if(symbol->type == LAMBDA)
    return fn_lambda(sexp,env);
  else if(symbol->type == FUNC)
    return (((func_object *) (symbol))->fn)(args, env);
  else
    return sexp;
}

object *eval (object *sexp, object *env) {
  if(sexp == NULL)
    return nil;

  if(sexp->type == CONS){
    if(car(sexp)->type == ATOM && strcmp(name(car(sexp)), "LAMBDA") == 0){
      object* largs = car(cdr(sexp));
      object* lsexp = car(cdr(cdr(sexp)));

      return lambda(largs,lsexp);
    }else{
      object *accum = cons(eval(car(sexp),env),NULL);
      sexp = cdr(sexp);

      while (sexp != NULL && sexp->type == CONS){
    append(accum,eval(car(sexp),env));
    sexp = cdr(sexp);
      }

      return eval_fn(accum,env);
    }
  }else{
    object *val = lookup(name(sexp),env);
    if(val == NULL)
      return sexp;
    else
      return val;
  }
}

//
// I/O
//
void print(object *sexp){
  if(sexp == NULL)
    return;

  if(sexp->type == CONS){
    printf ("(");
    print(car(sexp));
    sexp = cdr(sexp);
    while (sexp != NULL && sexp->type == CONS) {
      printf (" ");
      print(car(sexp));
      sexp = cdr(sexp);
    }
    printf ( ")");
  }else if(sexp->type == ATOM){
    printf ("%s", name(sexp));
  }else if(sexp->type == LAMBDA){
    printf ("#");
    print((((lambda_object *) (sexp))->args));
    print((((lambda_object *) (sexp))->sexp));
  }else
    printf ("Error.");
}

object *next_token(FILE *in) {
  int ch = getc(in);

  while(isspace(ch)) ch = getc(in);

  if(ch == '\n')
    ch = getc(in);
  if(ch == EOF)
    exit(0);

  if(ch == ')')
    return atom(")");
  if(ch == '(')
    return atom("(");

  char buffer[128];
  int index = 0;

  while(!isspace(ch) && ch != ')'){
    buffer[index++] = ch;
    ch = getc (in);
  }

  buffer[index++] = '\0';
  if (ch == ')')
    ungetc (ch, in);

  return atom(buffer);
}

object *read_tail(FILE *in) {
  object *token = next_token(in);

  if(strcmp(name(token),")") == 0)
    return NULL;
  else if(strcmp(name(token),"(") == 0) {
    object *first = read_tail(in);
    object *second = read_tail(in);
    return cons(first, second);
  }else{
    object *first = token;
    object *second = read_tail(in);
    return cons(first, second);
  }
}

object *read(FILE *in) {
  object *token = next_token(in);

  if(strcmp(name(token),"(") == 0)
    return read_tail(in);

  return token;
}

//
// REPL
//
int main(int argc, char *argv[]){
  object *env = init_env();
  FILE* in;

  if(argc > 1)
    in = fopen(argv[1], "r");
  else
    in = stdin;

  do {
    printf ("> ");
    print(eval(read(in), env));
    printf ("\n");
  } while (1);

  return 0;
}

Name: Anonymous 2011-08-13 17:22

>>7
I don't see which part of that code frees the memory allocated through malloc.

Name: Anonymous 2011-08-13 23:44

>>9
it happens to be a crappy toy implementation!

Name: Anonymous 2011-08-13 23:47

>>9
Not properly managing your memory in non-GC languages, even in toy projects, is a sign of an amateur suffering from GC-induced brain rot.

Name: Anonymous 2011-08-13 23:53

>>8-10
It's a crappy toy implementation found on the internet, in a blog post.
It doesn't even use tagged pointers nor unboxed fixnums.

Name: Haxus the Dazed 2011-08-14 13:48

i am so high i dont even know what a ``tagged ptr'' is

Name: Anonymous 2011-08-14 14:08

>>12
cONS POINTERS. g'READ BOUT EM.

Name: Anonymous 2011-08-14 14:14

>>11
It's not even yours? Poor show.
>>12
Me neither and I'm as sober as a cop.

Name: Anonymous 2011-08-14 19:43

>>10
new C programmers who have never used GC are also terrible at managing memory.

GC does not cause brain rot half as bad as C++ does.

Name: Anonymous 2011-08-14 20:05

>>14
I'm not >>7 nor the author. Kindly fuck yourself.

Name: Anonymous 2011-08-14 21:55

from implementations import commonlisp

Name: Anonymous 2011-08-15 12:09

Nobody here can implement Lisp by themselves.

Name: Anonymous 2011-08-15 12:14

>>18
Nobody here can implement Lisp by themselves.
I hope some people took the SICP spamming seriously and have actually read it.

Name: Anonymous 2011-08-15 12:27

SICP is terrible.

Name: 2011-08-15 12:35

Name: Anonymous 2011-08-15 13:07

>>20
No it's not you fetid piece of shit.

Name: Anonymous 2011-08-15 13:49

>>22
Yet another butthurt SICP evangelist.

Name: Anonymous 2011-08-15 15:37

>>23
You clueless double nigger. Go take your micropenis and shove it up your mothers anus and scream "I'VE BEEN A BAD BOY".

Name: Anonymous 2011-08-15 15:58

>>24
Trying too hard. Take your buttfrustration elsewhere.

Name: Anonymous 2011-08-15 16:05

NIGGERS

Name: Anonymous 2011-08-15 16:09

>>25
FuCk OfF to the StOrMY MOunTS of FAGGOTness

Name: Anonymous 2011-08-15 16:29

>>27
Cool story, bro. Here, have some polecat kebabs on me!

Name: Anonymous 2011-08-15 16:43

>>28
fuck you fagstorm

Name: Anonymous 2011-08-15 17:42

Very last lines of the aforementioned textbook:

Exercise 5.51.  Develop a rudimentary implementation of Scheme in C (or some other low-level language of your choice) by translating the explicit-control evaluator of section 5.4 into C. In order to run this code you will need to also provide appropriate storage-allocation routines and other run-time support.
Exercise 5.52.  As a counterpoint to exercise 5.51, modify the compiler so that it compiles Scheme procedures into sequences of C instructions. Compile the metacircular evaluator of section 4.1 to produce a Scheme interpreter written in C.

Name: Anonymous 2011-08-15 21:10

If you haven't read SICP, you don't belong on /prog/.

Name: n3n7i 2011-08-15 22:49

...though most of it you will eventually come across anyway, and probably have more fun solving it yourself... =)

Name: Anonymous 2011-08-18 2:45

Mission failed.

Name: Anonymous 2011-08-18 2:47

>>33
I would, but I'm not at home this month.

Name: Anonymous 2011-08-18 5:26

I've tried to implement the Lisp found in ``Recursive Functions of Symbolic Expressions and Their Computation by Machine, Part I'' [McCarthy60] two times and failed twice ;_;

Name: Anonymous 2011-08-18 12:56

>>35
How u fail?

Name: Anonymous 2011-08-18 14:49

>>36
I think they just didn't work as they should.  I might give it a shot some time, as I did see something in the article that might be of interest.

I also heard that the implementation in the article was broken by design ...

Name: Anonymous 2011-08-19 1:42

>>35
McCarthy's eval has a bug in it btw.

Don't change these.
Name: Email:
Entire Thread Thread List