Example #1
0
File: eval.c Project: hmarr/skeema
sk_Object *sk_eval(sk_VM *vm, sk_Object *exp)
{
    debug_obj("eval: %s", exp);

    if (sk_object_is(exp, sk_SymbolType)) {
        // direct eval() on symbol means we look it up
        debug_obj("symbol lookup: %s", exp);
        sk_Object *var = sk_dict_get(vm->scope, sk_symbol_cstr(exp));
        if (var == NULL) {
            // symbol not in present in scope
            error_obj("undefined identifier: %s", exp);
        }
        return sk_inc_ref(var);
    }

    if (!sk_object_is(exp, sk_CellType)) {
        // only symbols and cells (lists) are special, return values as is
        debug_obj("atom: %s", exp);
        return sk_inc_ref(exp);
    }

    // special form: def
    if (sk_symbol_is(vm, sk_cell_car(exp), "def")) {
        return sk_eval_def(vm, exp);
    }

    // special form: quote
    if (sk_symbol_is(vm, sk_cell_car(exp), "quote")) {
        return sk_inc_ref(sk_cell_car(sk_cell_cdr(exp)));
    }

    // special form: lambda
    if (sk_symbol_is(vm, sk_cell_car(exp), "lambda") ||
        sk_symbol_is(vm, sk_cell_car(exp), "->")) {
        return sk_eval_lambda(vm->scope, exp);
    }

    // we've got a list, which means function invocation
    // start by resolving the function
    sk_Object *result, *proc = sk_eval(vm, sk_cell_car(exp));
    if (proc == NULL) {
        // function doesn't exists, but they already got an error from above
        result = NULL;
    } else if (sk_object_is(proc, sk_ProcType)) {
        result = sk_proc_apply(vm, proc, sk_cell_cdr(exp));
    } else if (sk_object_is(proc, sk_LambdaType)) {
        result = sk_lambda_apply(vm, proc, sk_cell_cdr(exp));
    } else {
        error_obj("expected procedure, got %s", proc);
        result = NULL;
    }
    sk_dec_ref(proc);

    return result;
}
Example #2
0
// Debug an object with extra verbosity, displaying non-enumerable properties.
void
fh_debug_verbose(FILE *stream, js_val *val, int indent)
{
  switch (val->type) {
    case T_BOOLEAN:
      fprintf(stream, "Boolean: (%s)", !val->boolean.val ? "false" : "true");
      break;
    case T_NUMBER:
      debug_num(stream, val);
      break;
    case T_STRING:
      cfprintf(stream, ANSI_YELLOW, "String: '%s'", val->string.ptr);
      break;
    case T_NULL:
      cfprintf(stream, ANSI_GRAY, "null");
      break;
    case T_UNDEF:
      cfprintf(stream, ANSI_GRAY, "undefined");
      break;
    case T_OBJECT:
      if (IS_ARR(val))
        fprintf(stream, "Array: ");
      else if (IS_FUNC(val))
        cfprintf(stream, ANSI_BLUE, "Function: ");
      else
        fprintf(stream, "Object: ");
      break;
  }

  if (IS_OBJ(val))
    debug_obj(stream, val, indent, true);

  fprintf(stream, "\n");
}
Example #3
0
void
fh_debug(FILE *stream, js_val *val, int indent, bool newline)
{
  switch (val->type) {
    case T_BOOLEAN:
      fprintf(stream, "%s", !val->boolean.val ? "false" : "true");
      break;
    case T_NUMBER:
      debug_num(stream, val);
      break;
    case T_STRING:
      if (fh->opt_interactive)
        cfprintf(stream, ANSI_YELLOW, "'%s'", val->string.ptr);
      else
        fprintf(stream, "%s", val->string.ptr);
      break;
    case T_NULL:
      cfprintf(stream, ANSI_GRAY, "null");
      break;
    case T_UNDEF:
      cfprintf(stream, ANSI_GRAY, "undefined");
      break;
    case T_OBJECT:
      if (IS_ARR(val))
        debug_arr(stream, val, indent);
      else if (IS_FUNC(val))
        cfprintf(stream, ANSI_BLUE, "[Function]");
      else if (IS_DATE(val))
        fprintf(stream, "[Date %ld]", (long)val->object.primitive->number.val);
      else
        debug_obj(stream, val, indent, false);
      break;
  }
  if (newline) fprintf(stream, "\n");
}
Example #4
0
File: eval.c Project: hmarr/skeema
sk_Object *sk_lambda_apply(sk_VM *vm, sk_Object *lambda, sk_Object *arg_exp)
{
    // cool, we've got a function
    debug_obj("calling lambda: %s", lambda);

    sk_Object *scope = sk_lambda_scope(lambda);

    sk_Object *arg = arg_exp, *arg_name = sk_lambda_args(lambda);

    while (arg != sk_nil && arg_name != sk_nil) {
        debug_obj("arg: %s", arg);
        debug_obj("arg name: %s", arg_name);
        // eval the arg
        sk_Object *evald_arg = sk_eval(vm, sk_cell_car(arg));
        if (evald_arg == NULL) {
            // something went wrong up the call stack when evalling
            error_obj("got NULL while evalling %s", arg_exp);
            sk_dec_ref(lambda);  // TODO: should this be here?? as above.
            return NULL;
        }

        sk_dict_set(scope, sk_string_cstr(sk_cell_car(arg_name)), evald_arg);
        sk_dec_ref(evald_arg);

        // next arg, repeat the evalling!
        arg = sk_cell_cdr(arg);
        arg_name = sk_cell_cdr(arg_name);
    }

    if (arg != sk_nil) {
        error_obj("too many args provided to %s", lambda);
        return NULL;
    }

    if (arg_name != sk_nil) {
        error_obj("too few args provided to %s", lambda);
        return NULL;
    }

    // we've got our list of evalled args, let's invoke the proc!
    //debug_obj("calling with args: %s", args);
    sk_Object *result = sk_eval(vm, sk_lambda_expr(lambda));

    return result;
}
Example #5
0
File: eval.c Project: hmarr/skeema
sk_Object *sk_proc_apply(sk_VM *vm, sk_Object *proc, sk_Object *arg_exp)
{
    // cool, we've got a function
    debug_obj("calling proc: %s", proc);

    // now we need to eval the args, one by one
    sk_Object *args = sk_nil;
    // loop through the list of unevaluated args
    while (arg_exp != sk_nil && sk_object_is(arg_exp, sk_CellType)) {
        // eval the arg
        sk_Object *evald_arg = sk_eval(vm, sk_cell_car(arg_exp));
        if (evald_arg == NULL) {
            // something went wrong up the call stack when evalling
            error_obj("got NULL while evalling %s", arg_exp);
            sk_dec_ref(proc);  // TODO: why is this here?
            return NULL;
        }

        if (args == sk_nil) {
            // start of the arg list, create the first element
            args = sk_cell_new(evald_arg, sk_nil);
        } else {
            // arg list already exists, append to the back
            sk_cell_append(args, evald_arg);
        }
        // evald arg is part of arg list now, doesn't need us any more
        sk_dec_ref(evald_arg);

        // next arg, repeat the evalling!
        arg_exp = sk_cell_cdr(arg_exp);
    }

    // we've got our list of evalled args, let's invoke the proc!
    debug_obj("calling with args: %s", args);
    sk_Object *result = sk_proc_fn(proc)(vm, vm->scope, args);
    // now that's out the way we're done with our args
    sk_dec_ref(args);
    return result;
}