<commit_before>#include "lisp.h"

static Object *syntax_if(Object *env, Object *form)
{
    // TODO: form validation

    // (if cond then else)

    Object *cond = form->cdr->car;
    Object *then_block = form->cdr->cdr->car;
    Object *else_block = Nil;

    if (ST_PAIRP(form->cdr->cdr->cdr))
    {
        else_block = form->cdr->cdr->cdr->car;
    }

    Object *result = St_Eval(env, cond);

    if (!ST_FALSEP(result))
    {
        return St_Eval(env, then_block);
    }
    else
    {
        return St_Eval(env, else_block);
    }
}

static Object *syntax_define(Object *env, Object *form)
{
    int len = St_Length(form->cdr);

    if (len != 2)
    {
        St_Error("define: malformed define");
    }

    Object *sym = form->cdr->car;
    Object *body = form->cdr->cdr->car;

    if (!ST_SYMBOLP(sym))
    {
        St_Error("define: symbol required");
    }

    Object *value = St_Eval(env, body);

    St_AddVariable(env, sym, value);

    return sym;
}

static Object *syntax_quote(Object *env, Object *form)
{
    int len = St_Length(form->cdr);

    if (len != 1)
    {
        St_Error("quote: malformed quote");
    }

    return form->cdr->car;
}

static Object *syntax_set(Object *env, Object *form)
{
    return Nil; // TODO
}

static bool nil_or_symbol_list(Object *obj)
{
    if (ST_NULLP(obj))
    {
        return true;
    }

    if (ST_PAIRP(obj))
    {
        bool r = true;
        for (Object *p = obj; r && !ST_NULLP(p); p = p->cdr) {
            r = r && ST_SYMBOLP(p->car);
        }
        return r;
    }

    return false;
}

static Object *syntax_lambda(Object *env, Object *form)
{
    // (lambda <params> <body>)
    // <params> ::= (<symbol> *)
    // <body> ::<define> * <expr> +

    int len = St_Length(form->cdr);

    if (len < 2)
    {
        St_Error("lambda: malformed lambda");
    }

    Object *params = form->cdr->car;
    Object *body = form->cdr->cdr;

    if (!nil_or_symbol_list(params))
    {
        St_Error("lambda: params needs to be () or a list of symbols");
    }

    // TODO: validate body

    Object *lambda = St_Alloc(TLAMBDA);
    lambda->params = params;
    lambda->env = env;
    lambda->body = body;

    return lambda;
}

static Object *syntax_call_cc(Object *env, Object *form)
{
    return Nil; // TODO
}

static Object *subr_plus(Object *env, Object *args)
{
    int len = St_Length(args);

    if (len != 2)
    {
        St_Error("+: wrong number of arguments");
    }

    Object *lhs = args->car;
    Object *rhs = args->cdr->car;

    if (!ST_INTP(lhs) || !ST_INTP(rhs))
    {
        St_Error("+: invalid type");
    }

    Object *o = St_Alloc(TINT);
    o->int_value = lhs->int_value + rhs->int_value;

    return o;
}

static Object *subr_minus(Object *env, Object *args)
{
    int len = St_Length(args);

    if (len > 2)
    {
        St_Error("-: wrong number of arguments");
    }<commit_msg>Fix to avoid (-)<commit_after>#include "lisp.h"

static Object *syntax_if(Object *env, Object *form)
{
    // TODO: form validation

    // (if cond then else)

    Object *cond = form->cdr->car;
    Object *then_block = form->cdr->cdr->car;
    Object *else_block = Nil;

    if (ST_PAIRP(form->cdr->cdr->cdr))
    {
        else_block = form->cdr->cdr->cdr->car;
    }

    Object *result = St_Eval(env, cond);

    if (!ST_FALSEP(result))
    {
        return St_Eval(env, then_block);
    }
    else
    {
        return St_Eval(env, else_block);
    }
}

static Object *syntax_define(Object *env, Object *form)
{
    int len = St_Length(form->cdr);

    if (len != 2)
    {
        St_Error("define: malformed define");
    }

    Object *sym = form->cdr->car;
    Object *body = form->cdr->cdr->car;

    if (!ST_SYMBOLP(sym))
    {
        St_Error("define: symbol required");
    }

    Object *value = St_Eval(env, body);

    St_AddVariable(env, sym, value);

    return sym;
}

static Object *syntax_quote(Object *env, Object *form)
{
    int len = St_Length(form->cdr);

    if (len != 1)
    {
        St_Error("quote: malformed quote");
    }

    return form->cdr->car;
}

static Object *syntax_set(Object *env, Object *form)
{
    return Nil; // TODO
}

static bool nil_or_symbol_list(Object *obj)
{
    if (ST_NULLP(obj))
    {
        return true;
    }

    if (ST_PAIRP(obj))
    {
        bool r = true;
        for (Object *p = obj; r && !ST_NULLP(p); p = p->cdr) {
            r = r && ST_SYMBOLP(p->car);
        }
        return r;
    }

    return false;
}

static Object *syntax_lambda(Object *env, Object *form)
{
    // (lambda <params> <body>)
    // <params> ::= (<symbol> *)
    // <body> ::<define> * <expr> +

    int len = St_Length(form->cdr);

    if (len < 2)
    {
        St_Error("lambda: malformed lambda");
    }

    Object *params = form->cdr->car;
    Object *body = form->cdr->cdr;

    if (!nil_or_symbol_list(params))
    {
        St_Error("lambda: params needs to be () or a list of symbols");
    }

    // TODO: validate body

    Object *lambda = St_Alloc(TLAMBDA);
    lambda->params = params;
    lambda->env = env;
    lambda->body = body;

    return lambda;
}

static Object *syntax_call_cc(Object *env, Object *form)
{
    return Nil; // TODO
}

static Object *subr_plus(Object *env, Object *args)
{
    int len = St_Length(args);

    if (len != 2)
    {
        St_Error("+: wrong number of arguments");
    }

    Object *lhs = args->car;
    Object *rhs = args->cdr->car;

    if (!ST_INTP(lhs) || !ST_INTP(rhs))
    {
        St_Error("+: invalid type");
    }

    Object *o = St_Alloc(TINT);
    o->int_value = lhs->int_value + rhs->int_value;

    return o;
}

static Object *subr_minus(Object *env, Object *args)
{
    int len = St_Length(args);

    if (len < 1 || 2 < len)
    {
        St_Error("-: wrong number of arguments");
    }
{'fraction_non_alphanumeric': 0.15729561917902726, 'fraction_numerical': 0.0018972059330803726, 'mean_word_length': 2.304273504273504, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 92, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1814521', 'n_tokens_mistral': 2180, 'n_tokens_neox': 2096, 'n_words': 501}