Example #1
0
object_t primitive_isnull(object_t argl) {
  if(isnull(car(argl))) {
    return obj_new_symbol("#t");
  } else {
    return obj_new_symbol("#f");
  }
}
Example #2
0
object_t primitive_file_append(object_t argl) {
  char *string = obj_get_string(car(argl));
  char *filename = obj_get_string(car(cdr(argl)));
  if(file_append(string, filename))
    return obj_new_symbol("#t");
  else
    return obj_new_symbol("#f");
}
Example #3
0
object_t primitive_read(object_t argl) {
  object_t r = parse_sexp(read_sexp(stdin));
  if(r == NULL)
    return obj_new_symbol("_empty_");
  else
    return r;
}
Example #4
0
object_t cmp_primitive(object_t argl, int (*f) (int, int)) {
  int arg1 = obj_get_number(car(argl));
  argl = cdr(argl);
  int arg2;
  object_t ret;
  while(!isnull(argl)) {
    arg2 = obj_get_number(car(argl));
    if(!f(arg1, arg2)) {
      ret = obj_new_symbol("#f");
      return ret;
    }
    arg1 = arg2;
    argl = cdr(argl);
  }
  ret = obj_new_symbol("#t");
  return ret;
}
Example #5
0
object_t parse_sexp2(char **in, object_t current) {
  char *buf;
  enum kind k = next_token(in, &buf);
  object_t rest, s;
  switch(k) {

  case End:
    return current;

  case Left:
    rest = parse_sexp2(in, NIL);
    if(current == NULL)
      return rest;
    else if(current == NIL)
      current = cons(rest, NIL);
    else
      storage_append(rest, current);

    return parse_sexp2(in, current);
    
  case Right:
    return current;

  case Period:
    rest = parse_sexp2(in, NULL);
    set_cdr(storage_last(current), rest);
    return parse_sexp2(in, current);

  
  case Single: /* following are reader-macros */
    return wrap(in, current, "quote");
  case Back:
    return wrap(in, current, "quasiquote");
  case Comma:
    return wrap(in, current, "unquote");

  case Symbol:
  case String:
    if(k == Symbol) {
      if(all_digits(buf))
        s = obj_new_number(atoi(buf));
      else
        s = obj_new_symbol(buf);
    }
    else if(k == String)
      s = obj_new_string(buf);

    if(current == NULL)
      return s;
    else if(current == NIL)
      return parse_sexp2(in, cons(s, NIL));
    else {
      storage_append(s, current);
      return parse_sexp2(in, current);
    }
  }
  return NULL;
}
Example #6
0
object_t primitive_eq(object_t argl) {
  object_t a1 = car(argl);
  object_t a2 = car(cdr(argl));

  int result;

  if(issymbol(a1) && issymbol(a2))
    result = obj_symbol_cmp(a1, a2);
  else if(isnum(a1) && isnum(a2))
    result = (obj_get_number(a1) == obj_get_number(a2));
  else
    result = 0;

  if(result)
    return obj_new_symbol("#t");
  else
    return obj_new_symbol("#f");
}
Example #7
0
object_t read_file(char *filename) {
  FILE *f = fopen(filename, "r");
  char *input;
  object_t seq = cons(obj_new_symbol("begin"), NIL);
  while((input = read_sexp(f)) != NULL) {
    object_t exp = parse_sexp(input);
    storage_append(exp, seq);
  }
  return seq;
}
Example #8
0
object_t wrap(char **in, object_t current, char *type) {
    object_t rest = parse_sexp2(in, NULL);
    object_t ret = cons(obj_new_symbol(type), cons(rest, NIL));

    if(current == NULL) {
      return ret;
    } else if(current == NIL) {
      current = cons(ret, NIL);
    } else {
      storage_append(ret, current);
    }

    return parse_sexp2(in, current);
}
Example #9
0
object_t primitive_set_cdr(object_t argl) {
  set_cdr(car(argl), car(cdr(argl)));
  return obj_new_symbol("ok");
}
Example #10
0
object_t primitive_numberp(object_t argl) {
  if(isnum(car(argl)))
      return obj_new_symbol("#t");
  else
    return obj_new_symbol("#f");
}
Example #11
0
object_t init_global() {
  object_t env = NIL;
  object_t primitives[] = {
    obj_new_symbol("+"),         obj_new_primitive(&primitive_add),
    obj_new_symbol("*"),         obj_new_primitive(&primitive_multiply),
    obj_new_symbol("-"),         obj_new_primitive(&primitive_subtract),
    obj_new_symbol("/"),         obj_new_primitive(&primitive_divide),
    obj_new_symbol("<"),         obj_new_primitive(&primitive_lessthan),

    obj_new_symbol(">"),         obj_new_primitive(&primitive_greaterthan),
    obj_new_symbol("="),         obj_new_primitive(&primitive_equals),
    obj_new_symbol("cons"),      obj_new_primitive(&primitive_cons),
    obj_new_symbol("car"),       obj_new_primitive(&primitive_car),
    obj_new_symbol("cdr"),       obj_new_primitive(&primitive_cdr),

    obj_new_symbol("null?"),     obj_new_primitive(&primitive_isnull),
    obj_new_symbol("eq?"),       obj_new_primitive(&primitive_eq),
    obj_new_symbol("set-cdr!"),  obj_new_primitive(&primitive_set_cdr),
    obj_new_symbol("set-car!"),  obj_new_primitive(&primitive_set_car),
    obj_new_symbol("symbol?"),   obj_new_primitive(&primitive_symbolp),

    obj_new_symbol("cons?"),     obj_new_primitive(&primitive_consp),
    obj_new_symbol("load"),      obj_new_primitive(&primitive_load),
    obj_new_symbol("print"),     obj_new_primitive(&primitive_print),
    obj_new_symbol("eval"),      obj_new_primitive(&primitive_eval),
    obj_new_symbol("apply"),     obj_new_primitive(&primitive_apply),

        obj_new_symbol("read"),      obj_new_primitive(&primitive_read),
    obj_new_symbol("read-file"), obj_new_primitive(&primitive_read_file),
    obj_new_symbol("quit"),      obj_new_primitive(&primitive_quit),
    obj_new_symbol("error"),     obj_new_primitive(&primitive_error),
    obj_new_symbol("string?"),   obj_new_primitive(&primitive_stringp),

    obj_new_symbol("number?"),   obj_new_primitive(&primitive_numberp),
    obj_new_symbol("file-append"),    obj_new_primitive(&primitive_file_append),
    obj_new_symbol("symbol->string"), obj_new_primitive(&primitive_symbol2string),
    obj_new_symbol("string->symbol"), obj_new_primitive(&primitive_string2symbol),
    obj_new_symbol("string-append"), obj_new_primitive(&primitive_string_append),

    obj_new_symbol("number->string"), obj_new_primitive(&primitive_number2string),
    obj_new_symbol("read-char"),    obj_new_primitive(&primitive_read_char),
    obj_new_symbol("string-length"),    obj_new_primitive(&primitive_string_length),
    obj_new_symbol("string="),    obj_new_primitive(&primitive_string_equals),
    obj_new_symbol("string-ref"),    obj_new_primitive(&primitive_string_ref)
  };

  int i;
  for(i = 0; i < 70; i+=2)
    env = define_variable(primitives[i], primitives[i+1], env);

  return env;
}
Example #12
0
object_t primitive_load(object_t argl) {
  load_file(obj_get_string(car(argl)), &global_env);
  return obj_new_symbol("loaded.");
}
Example #13
0
object_t make_compiled_procedure(object_t entry, object_t environment) {
  return cons(obj_new_symbol("compiled-procedure"),
              cons(entry,
                   cons(environment, NIL)));
}
Example #14
0
void print_generic_array_or_struct(Process *process, Obj *total, Obj *type_lookup, struct Obj *arg_to_str_obj) {
    assert(total);
    assert(total->tag == 'S');
    assert(type_lookup);
    assert(arg_to_str_obj);

    shadow_stack_push(process, total);
    shadow_stack_push(process, type_lookup);
    shadow_stack_push(process, arg_to_str_obj);

    Obj *reffed_arg_type = obj_list(obj_new_keyword("ref"), type_lookup); // HACK: ref needed when sending arrays into str
    Obj *args_type = obj_list(reffed_arg_type);
    Obj *signature = obj_list(obj_new_keyword("fn"), args_type, type_string);
    Obj *quoted_sig = obj_list(lisp_quote, signature);

    //printf("quoted_sig: %s\n", obj_to_string(quoted_sig)->s);

    Obj *generic_name_result = generic_name(process, "prn", quoted_sig);
    if(eval_error) {
        return;
    }
    shadow_stack_push(process, generic_name_result);

    bake_generic_primop_auto(process, "prn", quoted_sig);
    if(eval_error) {
        return;
    }

    // TODO: why this conversion?
    char *generic_name = obj_to_string_not_prn(process, generic_name_result)->s;
    //printf("generic_name 1: %s\n", generic_name);

    Obj *call_to_str = obj_list(obj_new_symbol(generic_name), (struct Obj *)arg_to_str_obj);

    //   OBS!!!
    //
    //   Calling obj_to_string on the call_to_str form will result in an infinite loop:
    //   printf("Call to str: %s\n", obj_to_string(call_to_str)->s);
    //
    //   DON'T DO IT!!!

    shadow_stack_push(process, call_to_str);

    Obj *array_to_string_result = NULL;
    if(BYTECODE_EVAL) {
        array_to_string_result = bytecode_sub_eval_form(process, process->global_env, call_to_str);
    }
    else {
        array_to_string_result = eval(process, process->global_env, call_to_str);
    }

    shadow_stack_push(process, array_to_string_result);
    if(eval_error) {
        printf("Error when calling str function for void ptr of type '%s':\n", obj_to_string(process, type_lookup)->s);
        printf("%s\n", obj_to_string(process, eval_error)->s);
        assert(false);
        stack_pop(process);
        obj_string_mut_append(total, "FAIL");
        return;
    }
    obj_string_mut_append(total, obj_to_string_not_prn(process, array_to_string_result)->s);

    Obj *pop1 = shadow_stack_pop(process);
    assert(pop1 == array_to_string_result);
    shadow_stack_pop(process);
    shadow_stack_pop(process);
    shadow_stack_pop(process);
    shadow_stack_pop(process);
    Obj *pop8 = shadow_stack_pop(process);
    assert(pop8 == total);

    return;
}
Example #15
0
File: eval.c Project: JonasG/Carp
void apply(Process *process, Obj *function, Obj **args, int arg_count) {
  if(function->tag == 'L') {

//printf("Calling lambda "); obj_print_cout(function); printf(" with params: "); obj_print_cout(function->params); printf("\n");
//printf("Applying %s with arg count %d\n", obj_to_string(process, function)->s, arg_count);

#if BYTECODE_EVAL

    Obj *calling_env = obj_new_environment(function->env);

    bool allow_rest_args = true;
    env_extend_with_args(process, calling_env, function, arg_count, args, allow_rest_args);

    //printf("calling_env: %s\n", obj_to_string(process, calling_env)->s);

    shadow_stack_push(process, function);
    shadow_stack_push(process, calling_env);

    /* printf("before\n"); */
    /* shadow_stack_print(process); */

    Obj *result = bytecode_sub_eval_internal(process, calling_env, function->body);

    if(eval_error) {
      return;
    }
    assert(result);

    //printf("result = %s\n", obj_to_string(process, result)->s);
    stack_push(process, result); // put it back on stack (TODO: fix this unnecessary work?)

    /* printf("after\n"); */
    /* shadow_stack_print(process); */

    Obj *pop1 = shadow_stack_pop(process);
    Obj *pop2 = shadow_stack_pop(process);
    assert(pop1 == calling_env);
    assert(pop2 == function);

#else

    Obj *calling_env = obj_new_environment(function->env);
    bool allow_rest_args = true;
    env_extend_with_args(process, calling_env, function, arg_count, args, allow_rest_args);
    //printf("Lambda env: %s\n", obj_to_string(calling_env)->s);

    shadow_stack_push(process, function);
    shadow_stack_push(process, calling_env);

    if(function->body->tag == 'X') {
      eval_error = obj_new_string("Can't apply lambda with bytecode body.");
    }
    else {
      eval_internal(process, calling_env, function->body);
    }

    if(eval_error) {
      return;
    }

    Obj *pop1 = shadow_stack_pop(process);
    Obj *pop2 = shadow_stack_pop(process);
    assert(pop1 == calling_env);
    assert(pop2 == function);
#endif
  }
  else if(function->tag == 'P') {
    Obj *result = function->primop((struct Process *)process, args, arg_count);
    stack_push(process, result);
  }
  else if(function->tag == 'F') {
    call_foreign_function(process, function, args, arg_count);
  }
  else if(function->tag == 'K') {
    if(arg_count != 1) {
      eval_error = obj_new_string("Args to keyword lookup must be a single arg.");
    }
    else if(args[0]->tag != 'E') {
      eval_error = obj_new_string("Arg 0 to keyword lookup must be a dictionary: ");
      obj_string_mut_append(eval_error, obj_to_string(process, args[0])->s);
    }
    else {
      Obj *value = env_lookup(process, args[0], function);
      if(value) {
        stack_push(process, value);
      }
      else {
        eval_error = obj_new_string("Failed to lookup keyword '");
        obj_string_mut_append(eval_error, obj_to_string(process, function)->s);
        obj_string_mut_append(eval_error, "'");
        obj_string_mut_append(eval_error, " in \n");
        obj_string_mut_append(eval_error, obj_to_string(process, args[0])->s);
        obj_string_mut_append(eval_error, "\n");
      }
    }
  }
  else if(function->tag == 'E' && obj_eq(process, env_lookup(process, function, obj_new_keyword("struct")), lisp_true)) {
    //printf("Calling struct: %s\n", obj_to_string(process, function)->s);
    if(obj_eq(process, env_lookup(process, function, obj_new_keyword("generic")), lisp_true)) {
      //printf("Calling generic struct constructor.\n");
      Obj *function_call_symbol = obj_new_symbol("dynamic-generic-constructor-call");
      shadow_stack_push(process, function_call_symbol);

      Obj **copied_args = malloc(sizeof(Obj *) * arg_count);
      for(int i = 0; i < arg_count; i++) {
        copied_args[i] = obj_copy(process, args[i]);
        if(args[i]->meta) {
          copied_args[i]->meta = obj_copy(process, args[i]->meta);
        }
      }

      Obj *carp_array = obj_new_array(arg_count);
      carp_array->array = copied_args;

      Obj *call_to_concretize_struct = obj_list(function_call_symbol,
                                                function,
                                                carp_array);

      shadow_stack_push(process, call_to_concretize_struct);
      eval_internal(process, process->global_env, call_to_concretize_struct);

      shadow_stack_pop(process);
      shadow_stack_pop(process);
    }
    else {
      call_struct_constructor(process, function, args, arg_count);
    }
  }
  else {
    set_error("Can't call non-function: ", function);
  }
}
Example #16
0
object_t primitive_string_equals(object_t argl) {
  int c = strcmp(obj_get_string(car(argl)), obj_get_string(car(cdr(argl))));
  return c==0 ? obj_new_symbol("#t") : obj_new_symbol("#f");
}
Example #17
0
void print_generic_array_or_struct(Obj *total, Obj *type_lookup, struct Obj *arg_to_str_obj) {
  assert(total);
  assert(total->tag == 'S');
  assert(type_lookup);
  assert(arg_to_str_obj);
  
  shadow_stack_push(total);
  shadow_stack_push(type_lookup);
  shadow_stack_push(arg_to_str_obj);
	
  Obj *reffed_arg_type = obj_list(obj_new_keyword("ref"), type_lookup); // HACK: ref needed when sending arrays into str
  Obj *args_type = obj_list(reffed_arg_type);
  Obj *signature = obj_list(obj_new_keyword("fn"), args_type, type_string);
  Obj *quoted_sig = obj_list(lisp_quote, signature);

  //printf("quoted_sig: %s\n", obj_to_string(quoted_sig)->s);
	
  Obj *call_to_generic_name = obj_list(obj_new_symbol("generic-name"), obj_new_string("str"), quoted_sig);

  shadow_stack_push(call_to_generic_name);
  Obj *generic_name_result = eval(global_env, call_to_generic_name);
  shadow_stack_push(generic_name_result);

  if(eval_error) {
    printf("Error when calling generic-name:\n");
    printf("%s\n", obj_to_string(eval_error)->s);
    return;
  }
  else {
    //printf("Generic name: %s\n", obj_to_string_not_prn(generic_name_result)->s);
  }

  // Also make sure this particular version of the str primop has been baked:
  Obj *call_to_bake_generic_primop_auto = obj_list(obj_new_symbol("bake-generic-primop-auto"), obj_new_string("str"), quoted_sig);
  shadow_stack_push(call_to_bake_generic_primop_auto);
  eval(global_env, call_to_bake_generic_primop_auto);

  if(eval_error) {
    printf("Error when calling bake-generic-primop-auto from print_generic_array_or_struct:\n");
    printf("%s\n", obj_to_string(eval_error)->s);
    function_trace_print();
    return;
  }
  else {
    //printf("%s should now exists\n", obj_to_string_not_prn(generic_name_result)->s);
  }

  char *generic_name = obj_to_string_not_prn(generic_name_result)->s;
  //printf("generic_name 1: %s\n", generic_name);

  Obj *call_to_str = obj_list(obj_new_symbol(generic_name), (struct Obj *)arg_to_str_obj);
  
  //   OBS!!!
  //
  //   Calling obj_to_string on the call_to_str form will result in an infinite loop:
  //   printf("Call to str: %s\n", obj_to_string(call_to_str)->s);
  //
  //   DON'T DO IT!!!

  shadow_stack_push(call_to_str);
  Obj *array_to_string_result = eval(global_env, call_to_str);
  shadow_stack_push(array_to_string_result);
  if(eval_error) {
    printf("Error when calling str function for void ptr of type '%s':\n", obj_to_string(type_lookup)->s);
    printf("%s\n", obj_to_string(eval_error)->s);
    assert(false);
    stack_pop();
    obj_string_mut_append(total, "FAIL");
    return;
  }
  obj_string_mut_append(total, obj_to_string_not_prn(array_to_string_result)->s);

  Obj *pop1 = shadow_stack_pop();
  assert(pop1 == array_to_string_result);
  shadow_stack_pop();
  shadow_stack_pop();
  shadow_stack_pop();
  shadow_stack_pop();
  shadow_stack_pop();
  shadow_stack_pop();
  Obj *pop8 = shadow_stack_pop();
  assert(pop8 == total);

  return;
}
Example #18
0
object_t primitive_string2symbol(object_t argl) {
  return obj_new_symbol(obj_get_string(car(argl)));
}
Example #19
0
object_t primitive_stringp(object_t argl) {
  if(isstring(car(argl)))
    return obj_new_symbol("#t");
  else
    return obj_new_symbol("#f");
}
Example #20
0
object_t primitive_consp(object_t argl) {
  if(iscons(car(argl)))
    return obj_new_symbol("#t");
  else
    return obj_new_symbol("#f");
}
Example #21
0
Process *process_new() {
  Process *process = malloc(sizeof(Process));
  process->dead = false;
  process->final_result = NULL;

#if BYTECODE_EVAL
  process->frame = 0;
#else
  process->frame = -1;
#endif

  process->bytecodeObj = NULL;
  pop_stacks_to_zero(process);

  process->global_env = obj_new_environment(NULL);

  nil = obj_new_cons(NULL, NULL);
  define("nil", nil);

  lisp_false = obj_new_bool(false);
  define("false", lisp_false);

  lisp_true = obj_new_bool(true);
  define("true", lisp_true);

  lisp_quote = obj_new_symbol("quote");
  define("quote", lisp_quote);

  ampersand = obj_new_symbol("&");
  define("&", ampersand);

  dotdotdot = obj_new_symbol("dotdotdot");
  define("dotdotdot", dotdotdot);

  hash = obj_new_keyword("hash");
  define("hash", hash);

  lisp_NULL = obj_new_ptr(NULL);
  define("NULL", lisp_NULL);

  type_ref = obj_new_keyword("ref");
  define("type_ref", type_ref);

  type_int = obj_new_keyword("int");
  define("type-int", type_int); // without this it will get GC'd!

  type_bool = obj_new_keyword("bool");
  define("type-bool", type_bool);

  type_float = obj_new_keyword("float");
  define("type-float", type_float);

  type_double = obj_new_keyword("double");
  define("type-double", type_double);

  type_string = obj_new_keyword("string");
  define("type-string", type_string);

  type_symbol = obj_new_keyword("symbol");
  define("type-symbol", type_symbol);

  type_keyword = obj_new_keyword("keyword");
  define("type-keyword", type_keyword);

  type_foreign = obj_new_keyword("foreign");
  define("type-foreign", type_foreign);

  type_primop = obj_new_keyword("primop");
  define("type-primop", type_primop);

  type_env = obj_new_keyword("env");
  define("type-env", type_env);

  type_macro = obj_new_keyword("macro");
  define("type-macro", type_macro);

  type_lambda = obj_new_keyword("lambda");
  define("type-lambda", type_lambda);

  type_list = obj_new_keyword("list");
  define("type-list", type_list);

  type_void = obj_new_keyword("void");
  define("type-void", type_void);

  type_ptr = obj_new_keyword("ptr");
  define("type-ptr", type_ptr);

  type_char = obj_new_keyword("char");
  define("type-char", type_char);

  type_array = obj_new_keyword("array");
  define("type-array", type_array);

  type_ptr_to_global = obj_new_keyword("ptr-to-global");
  define("type-ptr-to-global", type_ptr_to_global);

  prompt = define("prompt", obj_new_string(PROMPT));
  prompt_unfinished_form = define("prompt-unfinished-form", obj_new_string(PROMPT_UNFINISHED_FORM));

  register_primop(process, "open", p_open_file);
  register_primop(process, "save", p_save_file);
  register_primop(process, "+", p_add);
  register_primop(process, "-", p_sub);
  register_primop(process, "*", p_mul);
  register_primop(process, "/", p_div);
  //register_primop(process, "mod", p_mod);
  register_primop(process, "=", p_eq);
  register_primop(process, "list", p_list);
  register_primop(process, "array", p_array);
  register_primop(process, "dictionary", p_dictionary);
  register_primop(process, "str", p_str);
  register_primop(process, "str-append!", p_str_append_bang);
  register_primop(process, "str-replace", p_str_replace);
  register_primop(process, "join", p_join);
  register_primop(process, "register", p_register);
  register_primop(process, "register-variable", p_register_variable);
  register_primop(process, "register-builtin", p_register_builtin);
  register_primop(process, "print", p_print);
  register_primop(process, "println", p_println);
  register_primop(process, "prn", p_prn);
  register_primop(process, "def?", p_def_QMARK);
  //register_primop(process, "system", p_system);
  register_primop(process, "get", p_get);
  register_primop(process, "get-maybe", p_get_maybe);
  register_primop(process, "dict-set!", p_dict_set_bang);
  register_primop(process, "dict-remove!", p_dict_remove_bang);
  register_primop(process, "first", p_first);
  register_primop(process, "rest", p_rest);
  register_primop(process, "cons", p_cons);
  register_primop(process, "cons-last", p_cons_last);
  register_primop(process, "concat", p_concat);
  register_primop(process, "nth", p_nth);
  register_primop(process, "count", p_count);
  register_primop(process, "map", p_map);
  register_primop(process, "map-copy", p_map); // only matters when compiling to C
  register_primop(process, "map2", p_map2);
  register_primop(process, "filter", p_filter);
  register_primop(process, "reduce", p_reduce);
  register_primop(process, "apply", p_apply);
  register_primop(process, "type", p_type);
  register_primop(process, "<", p_lt);
  register_primop(process, "env", p_env);
  register_primop(process, "load-lisp", p_load_lisp);
  register_primop(process, "load-dylib", p_load_dylib);
  register_primop(process, "unload-dylib", p_unload_dylib);
  register_primop(process, "read", p_read);
  register_primop(process, "read-many", p_read_many);
  register_primop(process, "code", p_code);
  register_primop(process, "copy", p_copy);
  register_primop(process, "now", p_now);
  register_primop(process, "name", p_name);
  register_primop(process, "symbol", p_symbol);
  register_primop(process, "keyword", p_keyword);
  register_primop(process, "error", p_error);
  register_primop(process, "keys", p_keys);
  register_primop(process, "values", p_values);
  register_primop(process, "signature", p_signature);
  register_primop(process, "eval", p_eval);
  register_primop(process, "meta-set!", p_meta_set_BANG);
  register_primop(process, "meta-get", p_meta_get);
  register_primop(process, "meta-get-all", p_meta_get_all);
  register_primop(process, "array-to-list", p_array_to_list);
  register_primop(process, "array-of-size", p_array_of_size);
  register_primop(process, "array-set!", p_array_set_BANG);
  register_primop(process, "array-set", p_array_set);
  register_primop(process, "gc", p_gc);
  register_primop(process, "hash", p_hash);
  register_primop(process, "delete", p_delete);
  register_primop(process, "stop", p_stop);
  register_primop(process, "parallell", p_parallell);
  register_primop(process, "bytecode", p_bytecode);
  register_primop(process, "eval-bytecode", p_bytecode_eval);
  register_primop(process, "lookup-in-substs-fast", p_lookup_in_substs_fast);
  register_primop(process, "replace-subst-from-right-fast", p_replace_subst_from_right_fast);
  register_primop(process, "types-exactly-eq?", p_types_exactly_eq);
  register_primop(process, "extend-substitutions-fast", p_extend_substitutions_fast);
  register_primop(process, "sort-by-fast", p_sort_by);

  Obj *abs_args = obj_list(type_int);
  register_ffi_internal(process, "abs", (VoidFn)abs, abs_args, type_int, true);

  Obj *exit_args = obj_list(type_int);
  register_ffi_internal(process, "exit", (VoidFn)exit, exit_args, type_void, true);

  Obj *getenv_args = obj_list(type_string);
  register_ffi_internal(process, "getenv", (VoidFn)getenv, getenv_args, type_string, true);

  //printf("Global env: %s\n", obj_to_string(env)->s);

  return process;
}