Example #1
0
File: eval.c Project: samsonjs/lake
static LakeVal *_lambda(LakeCtx *ctx, Env *env, LakeList *expr)
{
    /* (lambda (a b c) ...) */
  if (LIST_N(expr) >= 3 && lake_is_type(TYPE_LIST, LIST_VAL(expr, 1))) {
    list_shift(expr); /* drop the "lambda" symbol */
    LakeList *params = LIST(list_shift(expr));
    LakeList *body = expr;
    return VAL(fn_make(params, NULL, body, env));
  }
  else if (LIST_N(expr) >= 3 && lake_is_type(TYPE_DLIST, LIST_VAL(expr, 1))) {
    list_shift(expr); /* drop the "lambda" symbol */
    LakeDottedList *def = DLIST(list_shift(expr));
    LakeList *params = dlist_head(def);
    LakeSym *varargs = SYM(dlist_tail(def));
    LakeList *body = expr;
    return VAL(fn_make(params, varargs, body, env));
  }
  else if (LIST_N(expr) >= 3 && lake_is_type(TYPE_SYM, LIST_VAL(expr, 1))) {
    list_shift(expr); /* drop the "lambda" symbol */
    LakeSym *varargs = SYM(list_shift(expr));
    LakeList *body = expr;
    return VAL(fn_make(list_make(), varargs, body, env));
  }
  else {
    invalid_special_form(expr, "lambda requires at least 2 parameters");
    return NULL;
  }
}
Example #2
0
File: eval.c Project: samsonjs/lake
LakeVal *apply(LakeCtx *ctx, LakeVal *fnVal, LakeList *args)
{
  LakeVal *result = NULL;
  if (lake_is_type(TYPE_PRIM, fnVal)) {
    LakePrimitive *prim = PRIM(fnVal);
    int arity = prim->arity;
    if (arity == ARITY_VARARGS || LIST_N(args) == arity) {
      result = prim->fn(ctx, args);
    }
    else {
      ERR("%s expects %d params but got %zu", prim->name, arity, LIST_N(args));
      result = NULL;
    }
  }
  else if (lake_is_type(TYPE_FN, fnVal)) {
    LakeFn *fn = FN(fnVal);

    /* Check # of params */
    size_t nparams = LIST_N(fn->params);
    if (!fn->varargs && LIST_N(args) != nparams) {
      ERR("expected %zu params but got %zu", nparams, LIST_N(args));
      return NULL;
    }
    else if (fn->varargs && LIST_N(args) < nparams) {
      ERR("expected at least %zu params but got %zu", nparams, LIST_N(args));
      return NULL;
    }

    Env *env = env_make(fn->closure);

    /* bind each (param,arg) pair in env */
    size_t i;
    for (i = 0; i < nparams; ++i) {
      env_define(env, SYM(LIST_VAL(fn->params, i)), LIST_VAL(args, i));
    }

    /* bind varargs */
    if (fn->varargs) {
      LakeList *remainingArgs = list_make_with_capacity(LIST_N(args) - nparams);
      for (; i < LIST_N(args); ++i) {
        list_append(remainingArgs, LIST_VAL(args, i));
      }
      env_define(env, fn->varargs, VAL(remainingArgs));
    }

    /* evaluate body */
    result = eval_exprs1(ctx, env, fn->body);
  }
  else {
    ERR("not a function: %s", lake_repr(fnVal));
  }
  return result;
}
Example #3
0
inline bool AVBufferListManager::RecycleIFrameList()
{
  bool release1stKeyframe = false;

  //recycle all video buffer beginning from keyframe
  FOR_LIST_ITERATOR_NOINC(AVBuffer*, _bufList, it) {
    AVBuffer* pBuffer = LIST_VAL(it);
    //recycle process is done
    if (release1stKeyframe && pBuffer->IsKeyFrame())
      break;
    if (!release1stKeyframe && (!pBuffer->IsKeyFrame())) {
      FATAL ("Error, first frame in video buffer is not key frame");
      return false;
    }

    if (pBuffer->IsKeyFrame() && !release1stKeyframe) {
      release1stKeyframe=true;
      _numOfKeyFrames -= 1;
      _IFrameList.pop_front();
    }
    _freeSize += pBuffer->getBufferSize();
    delete _bufList.front();
    it++;
    _bufList.pop_front();

    if (_bufList.size() == 0) {
      FATAL("_videoBuf.size == 0");
      return false;
    }
  }//FOR_LIST_ITERATOR
Example #4
0
File: eval.c Project: samsonjs/lake
LakeList *eval_exprs(LakeCtx *ctx, Env *env, LakeList *exprs)
{
  LakeList *results = list_make_with_capacity(LIST_N(exprs));
  int i;
  for (i = 0; i < LIST_N(exprs); ++i) {
    list_append(results, eval(ctx, env, LIST_VAL(exprs, i)));
  }
  return results;
}
Example #5
0
File: eval.c Project: samsonjs/lake
static LakeVal *eval_special_form(LakeCtx *ctx, Env *env, LakeList *expr)
{
  LakeSym *name = SYM(LIST_VAL(expr, 0));
  special_form_handler handler = get_special_form_handler(ctx, name);
  if (handler) {
    return handler(ctx, env, list_copy(expr));
  }
  ERR("unrecognized special form: %s", sym_repr(name));
  return NULL;
}
Example #6
0
File: eval.c Project: samsonjs/lake
static LakeVal *_define(LakeCtx *ctx, Env *env, LakeList *expr)
{
  /* TODO: make these more robust, check all expected params */

  /* (define x 42) */
  if (LIST_N(expr) == 3 && lake_is_type(TYPE_SYM, LIST_VAL(expr, 1))) {
    list_shift(expr); /* drop the "define" symbol */
    LakeSym *var = SYM(list_shift(expr));
    LakeVal *form = list_shift(expr);
    env_define(env, var, eval(ctx, env, form));
  }

  /* (define (inc x) (+ 1 x)) */
  else if (LIST_N(expr) >= 3 && lake_is_type(TYPE_LIST, LIST_VAL(expr, 1))) {
    list_shift(expr); /* drop the "define" symbol */
    LakeList *params = LIST(list_shift(expr));
    LakeSym *var = SYM(list_shift(params));
    LakeList *body = expr;
    env_define(env, var, VAL(fn_make(params, NULL, body, env)));
  }

  /* (define (print format . args) (...)) */
  else if (LIST_N(expr) >= 3 && lake_is_type(TYPE_DLIST, LIST_VAL(expr, 1))) {
    list_shift(expr); /* drop the "define" symbol */
    LakeDottedList *def = DLIST(list_shift(expr));
    LakeList *params = dlist_head(def);
    LakeSym *varargs = SYM(dlist_tail(def));
    LakeSym *var = SYM(list_shift(params));
    LakeList *body = expr;
    env_define(env, var, VAL(fn_make(params, varargs, body, env)));
  }

  else {
    invalid_special_form(expr, "define requires at least 2 parameters");
  }

  return NULL;
}
Example #7
0
File: eval.c Project: samsonjs/lake
static LakeVal *_if(LakeCtx *ctx, Env *env, LakeList *expr)
{
  if (LIST_N(expr) != 3) {
    invalid_special_form(expr, "if requires 3 parameters");
    return NULL;
  }
  list_shift(expr); /* "if" token */
  LakeVal *cond = eval(ctx, env, list_shift(expr));
  if (lake_is_truthy(ctx, cond)) {
    return eval(ctx, env, list_shift(expr));
  }
  else {
    return eval(ctx, env, LIST_VAL(expr, 1));
  }
}
Example #8
0
File: eval.c Project: samsonjs/lake
static LakeVal *_setB(LakeCtx *ctx, Env *env, LakeList *expr)
{
  /* (set! x 42) */
  if (LIST_N(expr) == 3 && lake_is_type(TYPE_SYM, LIST_VAL(expr, 1))) {
    list_shift(expr); /* drop the "set!" symbol */
    LakeSym *var = SYM(list_shift(expr));
    LakeVal *form = list_shift(expr);
    if (!env_set(env, var, form)) {
      ERR("%s is not defined", sym_repr(var));
    }
  }
  else {
    invalid_special_form(expr, "set! requires exactly 2 parameters");
  }
  return NULL;
}
Example #9
0
File: eval.c Project: samsonjs/lake
static LakeVal *_cond(LakeCtx *ctx, Env *env, LakeList *expr)
{
  static LakeVal *ELSE = NULL;
  if (!ELSE) ELSE = VAL(sym_intern(ctx, "else"));

  list_shift(expr); /* "cond" token */
  LakeVal *pred;
  LakeList *conseq;
  while (LIST_N(expr)) {
    if (!lake_is_type(TYPE_LIST, LIST_VAL(expr, 0))) {
      invalid_special_form(expr, "expected a (predicate consequence) pair");
      return NULL;
    }
    conseq = LIST(list_shift(expr));
    pred = list_shift(conseq);
    if (pred == ELSE || lake_is_truthy(ctx, eval(ctx, env, pred))) {
      return eval_exprs1(ctx, env, conseq);
    }
  }
  return NULL;
}
Example #10
0
File: eval.c Project: samsonjs/lake
LakeVal *eval(LakeCtx *ctx, Env *env, LakeVal *expr)
{
  LakeVal *result;
  LakeList *list;

  switch (expr->type) {

    /* self evaluating types */
    case TYPE_BOOL:
    case TYPE_INT:
    case TYPE_STR:
      result = expr;
      break;

    case TYPE_SYM:
      result = env_get(env, (void *)SYM(expr));
      if (!result) {
        ERR("undefined variable: %s", sym_repr(SYM(expr)));
      }
      break;

    case TYPE_DLIST:
      ERR("malformed function call");
      result = NULL;
      break;

    case TYPE_COMM:
      result = NULL;
      break;

    case TYPE_LIST:
      list = LIST(expr);

      if (LIST_N(list) == 0) {
        result = expr;
      }
      else {
        if (is_special_form(ctx, list)) {
          result = eval_special_form(ctx, env, list);
        }
        else {
          LakeVal *fn = eval(ctx, env, LIST_VAL(list, 0));
          if (!fn) {
            return NULL;
          }
          LakeList *args = list_make_with_capacity(LIST_N(list) - 1);
          int i;
          LakeVal *v;
          for (i = 1; i < LIST_N(list); ++i) {
            v = eval(ctx, env, LIST_VAL(list, i));
            if (v != NULL) {
              list_append(args, v);
            }
            else {
              list_free(args);
              result = NULL;
              goto done;
            }
          }
          result = apply(ctx, fn, args);
        }
      }
      break;

    default:
      ERR("unrecognized value, type %d, size %zu bytes", expr->type, expr->size);
      DIE("we don't eval that around here!");
  }

  done: return result;
}
Example #11
0
File: eval.c Project: samsonjs/lake
bool is_special_form(LakeCtx *ctx, LakeList *expr)
{
  LakeVal *head = LIST_VAL(expr, 0);
  if (!lake_is_type(TYPE_SYM, head)) return FALSE;
  return lake_hash_has(ctx->special_form_handlers, SYM(head)->s);
}