Пример #1
0
int main (int argc, char **argv) {
  // parse args
  struct arguments arguments;
  arguments.argc = 0;
  argp_parse (&argp, argc, argv, 0, 0, &arguments);
  char *filename = arguments.args[0];

  LClosure *closure = l_closure_new(NULL);
  l_closure_set_funcs(closure);

  LValue* f = l_value_new(L_STR_TYPE, closure);
  f->core.str = make_stringbuf((char*)filename);
  l_closure_set(closure, "-script", f, true);

  LValue *arg;
  LValue *args = l_value_new(L_LIST_TYPE, closure);
  args->core.list = create_vector();
  int i;
  for(i=1; i<arguments.argc; i++) {
    arg = l_value_new(L_STR_TYPE, closure);
    arg->core.str = make_stringbuf(arguments.args[i]);
    vector_add(args->core.list, arg, sizeof(arg));
  }
  l_closure_set(closure, "-args", args, true);

  l_eval_path(filename, closure);

  exit(0);
}
Пример #2
0
LValue *l_eval_call_args(LNode *node, LValue *func, LClosure *outer_closure, LClosure *inner_closure) {
  int i, argc;
  LValue *v, *args_val, **ref;
  LNode **args;

  if(node != NULL) {
    argc = node->exprc;
    args = node->exprs;
  } else {
    argc = 0;
    args = NULL;
  }

  if(outer_closure != inner_closure) {
    // initialize all args to nil
    for(i=0; i<func->core.func.argc; i++) {
      v = l_value_new(L_NIL_TYPE, inner_closure);
      l_closure_set(inner_closure, func->core.func.args[i]->val, v, true);
    }
  }

  // setup the arguments
  args_val = l_value_new(L_LIST_TYPE, inner_closure);
  args_val->core.list = create_vector();

  LValue ***args_ref = malloc(sizeof(LValue**) * argc);

  // set all passed args
  for(i=0; i<argc; i++) {
    if(args[i]->type == L_VAR_TYPE) { // pass vars by reference
      ref = l_closure_get_ref(outer_closure, args[i]->val);
      if(ref != NULL) {
        args_ref[i] = ref;
        v = *ref;
      } else {
        // handle error
        l_eval_var_node(args[i], outer_closure);
      }
    } else { // eval as normal and set the value
      v = l_eval_node(args[i], outer_closure);
      ref = malloc(sizeof(LValue*));
      *ref = v;
      args_ref[i] = ref;
    }
    // append to 'args' variable
    vector_add(args_val->core.list, v, sizeof(v));
  }

  for(i=0; i<func->core.func.argc; i++) {
    l_ref_put(inner_closure->locals, func->core.func.args[i]->val, args_ref[i]);
  }

  l_closure_set(inner_closure, "args", args_val, true);

  return args_val;
}
Пример #3
0
LValue *l_eval_string_node(LNode *node, LClosure *closure) {
  LValue *value = l_value_new(L_STR_TYPE, closure);
  if(strchr(node->val, '\\')) {
    value->core.str = make_stringbuf("");
    int i, len = strlen(node->val);
    char c[] = " ";
    for(i=0; i<len; i++) {
      if(node->val[i] == '\\' && i < len-1) {
        i++;
        switch(node->val[i]) {
          case 'a' : c[0] = '\a'; break;
          case 'b' : c[0] = '\b'; break;
          case 'f' : c[0] = '\f'; break;
          case 'n' : c[0] = '\n'; break;
          case 'r' : c[0] = '\r'; break;
          case 't' : c[0] = '\t'; break;
          case 'v' : c[0] = '\v'; break;
          case '\'': c[0] = '\''; break;
          case '"' : c[0] = '"' ; break;
          case '\\': c[0] = '\\'; break;
          case '?' : c[0] = '?' ; break;
        }
      } else {
        c[0] = node->val[i];
      }
      concat_stringbuf(value->core.str, c);
    }
  } else {
    value->core.str = make_stringbuf(node->val);
  }
  return value;
}
Пример #4
0
LValue *l_func_count(LValue *args, LClosure *closure) {
  LValue *list = l_list_get(args, 0);
  l_assert_is(list, L_LIST_TYPE, L_ERR_MISSING_LIST, closure);
  LValue *value = l_value_new(L_NUM_TYPE, closure);
  mpz_init_set_ui(value->core.num, list->core.list->length);
  return value;
}
Пример #5
0
// FIXME this does not work as expected/desired for a multi-character delimiter
// since it uses strtok under the hood
LValue *l_func_str_split(LValue *args, LClosure *closure) {
  LValue *string = l_list_get(args, 0);
  LValue *delim = l_list_get(args, 1);
  l_assert_is(string, L_STR_TYPE, L_ERR_MISSING_STR, closure);
  l_assert_is(delim, L_STR_TYPE, L_ERR_MISSING_STR, closure);
  int i, size;
  char **strings = str_split(string->core.str->str, delim->core.str->str, &size);
  LValue *value = l_value_new(L_LIST_TYPE, closure);
  value->core.list = create_vector();
  LValue *s;
  for(i=0; i<size; i++) {
    s = l_value_new(L_STR_TYPE, closure);
    s->core.str = make_stringbuf(strings[i]);
    vector_add(value->core.list, s, sizeof(s));
  }
  return value;
}
Пример #6
0
LValue *l_func_str_add(LValue *args, LClosure *closure) {
  LValue *v1 = l_list_get(args, 0);
  LValue *v2 = l_list_get(args, 1);
  LValue *value = l_value_new(L_STR_TYPE, closure);
  value->core.str = make_stringbuf("");
  concat_stringbuf(value->core.str, v1->core.str->str);
  concat_stringbuf(value->core.str, v2->core.str->str);
  return value;
}
Пример #7
0
LValue *l_func_list_get(LValue *args, LClosure *closure) {
  LValue *list = l_list_get(args, 0);
  LValue *index = l_list_get(args, 1);
  l_assert_is(list, L_LIST_TYPE, L_ERR_MISSING_LIST, closure);
  l_assert_is(index, L_NUM_TYPE, L_ERR_MISSING_INDEX, closure);
  LValue *value = l_list_get(list, mpz_get_si(index->core.num));
  if(value == NULL) value = l_value_new(L_NIL_TYPE, closure);
  return value;
}
Пример #8
0
LValue *l_eval_list_node(LNode *node, LClosure *closure) {
  LValue *value = l_value_new(L_LIST_TYPE, closure);
  value->core.list = create_vector();
  LValue *v;
  int i;
  for(i=0; i<node->exprc; i++) {
    v = l_eval_node(node->exprs[i], closure);
    vector_add(value->core.list, v, sizeof(v));
  }
  return value;
}
Пример #9
0
LValue *l_func_list_add(LValue *args, LClosure *closure) {
  LValue *l1 = l_list_get(args, 0);
  LValue *l2 = l_list_get(args, 1);
  LValue *value = l_value_new(L_LIST_TYPE, closure);
  value->core.list = subvector(l1->core.list, 0, l1->core.list->length);
  int i;
  for(i=0; i<l2->core.list->length; i++) {
    vector_add(value->core.list, l2->core.list->data[i], l2->core.list->sizes[i]);
  }
  return value;
}
Пример #10
0
LValue *l_func_rest(LValue *args, LClosure *closure) {
  LValue *list = l_list_get(args, 0);
  l_assert_is(list, L_LIST_TYPE, L_ERR_MISSING_LIST, closure);
  LValue *value = l_value_new(L_LIST_TYPE, closure);
  if(list->core.list->length > 1) {
    value->core.list = subvector(list->core.list, 1, list->core.list->length);
  } else {
    value->core.list = create_vector();
  }
  return value;
}
Пример #11
0
LValue *l_func_str(LValue *args, LClosure *closure) {
  LValue *value = l_value_new(L_STR_TYPE, closure);
  value->core.str = make_stringbuf("");
  char *s;
  int i;
  for(i=0; i<args->core.list->length; i++) {
    s = l_str(l_list_get(args, i));
    concat_stringbuf(value->core.str, s);
  }
  return value;
}
Пример #12
0
LValue *l_eval_var_node(LNode *node, LClosure *closure) {
  LValue *value = l_closure_get(closure, node->val);
  if(value != NULL) {
    return value;
  } else {
    value = l_value_new(L_ERR_TYPE, closure);
    value->core.str = make_stringbuf(node->val);
    buffer_concat(value->core.str, " not found");
    l_handle_error(value, node, closure);
    return value;
  }
}
Пример #13
0
LValue *l_func_add(LValue *args, LClosure *closure) {
  LValue *v1 = l_list_get(args, 0);
  LValue *v2 = l_list_get(args, 1);
  if(v1->type == L_LIST_TYPE && v2->type == L_LIST_TYPE) {
    return l_func_list_add(args, closure);
  } else if(v1->type == L_NUM_TYPE && v2->type == L_NUM_TYPE) {
    return l_func_num_add(args, closure);
  } else if(v1->type == L_STR_TYPE && v2->type == L_STR_TYPE) {
    return l_func_str_add(args, closure);
  } else {
    return l_value_new(L_NIL_TYPE, closure);
  }
}
Пример #14
0
LValue *l_eval_func_node(LNode *node, LClosure *closure) {
  LValue *value = l_value_new(L_FUNC_TYPE, closure);
  value->core.func.ptr = NULL;
  // pass node=NULL to l_closure_clone, so this lexical frame is not printed in a stack trace
  value->core.func.closure = l_closure_clone(closure, NULL);
  if(node->exprs[0]) {
    value->core.func.argc = node->exprs[0]->exprc;
    value->core.func.args = node->exprs[0]->exprs;
  } else {
    value->core.func.argc = 0;
  }
  value->core.func.exprc = node->exprs[1]->exprc;
  value->core.func.exprs = node->exprs[1]->exprs;
  return value;
}
Пример #15
0
void l_eval_path(const char *filename, LClosure *closure) {
  FILE *fp = fopen(filename, "r");
  if(fp == NULL) {
    printf("An error occurred while opening the file %s.\n", filename);
    exit(1);
  }

  LValue* f = l_value_new(L_STR_TYPE, closure);
  f->core.str = make_stringbuf((char*)filename);
  l_closure_set(closure, "-filename", f, true);

  stringbuf *source = make_stringbuf("");
  source->str = saferead(fp);

  l_eval(source->str, filename, closure);
}
Пример #16
0
LValue *l_func_type(LValue *args, LClosure *closure) {
  LValue *value = l_list_get(args, 0);
  char *types[9] = {
    "nil",
    "boolean",
    "boolean",
    "error",
    "number",
    "string",
    "variable",
    "list",
    "function"
  };
  LValue *repr = l_value_new(L_STR_TYPE, closure);
  repr->core.str = make_stringbuf(types[value->type]);
  return repr;
}
Пример #17
0
LValue *l_eval_error_node(LNode *node, LClosure *closure) {
  LValue *value = l_value_new(L_ERR_TYPE, closure);
  value->core.str = make_stringbuf(node->val);
  return value;
}
Пример #18
0
LValue *l_eval_num_node(LNode *node, LClosure *closure) {
  LValue *value = l_value_new(L_NUM_TYPE, closure);
  mpz_init_set_str(value->core.num, node->val, 0);
  return value;
}
Пример #19
0
// sets misc global vars
void l_create_globals(LClosure *closure) {
  l_closure_set(closure, "nil",   l_value_new(L_NIL_TYPE,   closure), false);
  l_closure_set(closure, "false", l_value_new(L_FALSE_TYPE, closure), false);
  l_closure_set(closure, "true",  l_value_new(L_TRUE_TYPE,  closure), false);
}
Пример #20
0
LValue *l_eval_call_node(LNode *node, LValue *func, LClosure *closure) {

  if(func == NULL) func = l_eval_var_node(node, closure);

  char *name = (node != NULL) ? node->val : "";

  LValue *value, *args_val;
  LNode *expr;
  int i;

  // create a running scope to hold arguments
  // and a reference to self (for recursion)
  // TODO this may not be necessary (can't we just do `cl=func->core.func.closure`?)
  LClosure *cl = l_closure_clone(func->core.func.closure, node);

tail_loop:

  l_debug(L_DEBUG_CALL) {
    if(node) printf(">>> entering %s on line %d in %s\n", name, node->line_no, node->source_file);
    else printf(">>> entering %s\n", name);
  }

  if(strcmp(name, "") != 0)
    l_closure_set(cl, name, func, true);

  args_val = l_eval_call_args(node, func, closure, cl);

  if(func->core.func.ptr != NULL) {
    // native C code
    if(!setjmp(cl->jmp)) {
      value = func->core.func.ptr(args_val, cl);
    } else {
      // function called longjmp to initiate a tail call
      l_debug(L_DEBUG_CALL) printf("^^^ reached end of %s (longjmp tail call)\n", name);
      node = NULL;
      func = l_closure_get(cl, "--tail-call--");
      closure = cl;
      l_closure_backfill(func->core.func.closure, cl, node);
      name = "";
      goto tail_loop;
    }
  } else {
    // Lydia code
    int exprc = func->core.func.exprc;
    if(exprc > 0) {
      // eval all but the last expression
      for(i=0; i<exprc-1; i++) {
        expr = func->core.func.exprs[i];
        value = l_eval_node(expr, cl);
      }
      expr = func->core.func.exprs[exprc-1];
      if(expr->type == L_CALL_TYPE) { // tail call
        l_debug(L_DEBUG_CALL) printf("^^^ reached end of %s (tail call)\n", name);
        node = expr;
        func = l_eval_var_node(node, cl);
        closure = cl;
        l_closure_backfill(func->core.func.closure, cl, node);
        name = node->val;
        goto tail_loop;
      } else {
        value = l_eval_node(expr, cl);
      }
    } else {
      value = l_value_new(L_NIL_TYPE, cl);
    }
  }

  l_closure_free(cl);

  l_debug(L_DEBUG_CALL) printf("<<< returning from %s\n", name);

  return value;
}