Beispiel #1
0
/*
 * Free an entire expression recursively.
 */
void freeExp(Exp *exp) {
    switch(exp->type) {
        case T_App:
            freeExp(exp->value->app->fun);
            freeExp(exp->value->app->arg);
            free(exp->value->app);
            free(exp->value);
            break;
        case T_Abs:
            freeExp(exp->value->abs->body);
            free(exp->value->abs);
            free(exp->value);
            break;
        case T_Var:
            free(exp->value->var);
            free(exp->value);
            break;
        case T_Con:
            free(exp->value->con);
            free(exp->value);
            break;
        case T_Opn:
            free(exp->value->opn);
            free(exp->value);
            break;
    }
    free(exp);
}
Beispiel #2
0
static exp_node *expression(void){
    exp_node *expn = newExpNode();
    
    if(match(TOKEN_LBRA,       NO_CONSUME) ||
       match(TOKEN_IDENTIFIER, NO_CONSUME) ||
       match(TOKEN_LITERAL,    NO_CONSUME))
	if((expn->termn = term()) != NULL)
	    if((expn->termtln = term_tail()) != error)
		return expn;

    freeExp(expn);
    return NULL;
}
Beispiel #3
0
/*
 * Perform reduction on a template until it reaches its normal form (when no
 * reduction rules are applicable).
 */
Exp *reduceTemplateNorm(Exp *exp) {
    Exp *initExp = copyExp(exp);

    bool normalForm = false;

    while(!normalForm) {
        Exp *redExp = reduceTemplate(initExp);
        normalForm = expEqual(initExp, redExp);
        freeExp(initExp);
        initExp = redExp;
    }

    return initExp;
}
Beispiel #4
0
/*
 * Perform at least one reduction step on the given template.
 */
Exp *reduceTemplate(Exp *exp) {

    // Conditionals
    if(isApp(exp)
            && isApp(appFun(exp))
            && isApp(appFun(appFun(exp)))
            && isOpn(appFun(appFun(appFun(exp))))
            && (opnType(appFun(appFun(appFun(exp)))) == O_Cond)) {

        Exp *guard  = appArg(appFun(appFun(exp)));
        Exp *truExp = appArg(appFun(exp));
        Exp *falExp = appArg(exp);

        // If the guard is true, return the true expression.
        if(isCon(guard) && (conVal(guard) == true)) {
            return copyExp(truExp);
        }
        // If the guard is false, return the false expression.
        else if(isCon(guard) && (conVal(guard) == false)) {
            return copyExp(falExp);
        }
        // If the guard is not reduced, reduce it.
        else {
            return newApp(newApp(newApp(
                            newOpn(O_Cond), reduceTemplate(guard)),
                        copyExp(truExp)), copyExp(falExp));
        }
    }
    // End of conditional case

    // Binary operations
    else if(isApp(exp)
            && isApp(appFun(exp))
            && isBinaryOpn(appFun(appFun(exp)))) {

        OpTy opn  = opnType(appFun(appFun(exp)));
        Exp *arg1 = appArg(appFun(exp));
        Exp *arg2 = appArg(exp);

        // Handle equality differently because it is polymorphic.
        if(opn == O_Equ) {
            Exp *redA1 = reduceTemplateNorm(arg1);
            Exp *redA2 = reduceTemplateNorm(arg2);
            bool same = expEqual(redA1, redA2);
            freeExp(redA1);
            freeExp(redA2);
            return newCon(C_Bool, same);
        }
        else if(isApp(arg1) || isAbs(arg1) || isVar(arg1) || isOpn(arg1)) {
            return newApp(
                    newApp(
                        newOpn(opn),
                        reduceTemplate(arg1)),
                    copyExp(arg2));
        }
        else if(isApp(arg2) || isAbs(arg2) || isVar(arg2) || isOpn(arg2)) {
            return newApp(
                    newApp(
                        newOpn(opn),
                        copyExp(arg1)),
                    reduceTemplate(arg2));
        }
        else {
            assert(isCon(arg1));
            assert(isCon(arg2));

            if(opn == O_Add) {
                return newCon(C_Int, conVal(arg1) + conVal(arg2));
            }
            else if(opn == O_Sub) {
                return newCon(C_Int, conVal(arg1) - conVal(arg2));
            }
            else if(opn == O_Mul) {
                return newCon(C_Int, conVal(arg1) * conVal(arg2));
            }
            else if(opn == O_Div) {
                return newCon(C_Int, conVal(arg1) / conVal(arg2));
            }
            else if(opn == O_Mod) {
                return newCon(C_Int, conVal(arg1) % conVal(arg2));
            }
            else if(opn == O_Lss) {
                return newCon(C_Bool, conVal(arg1) < conVal(arg2));
            }
            else if(opn == O_LsE) {
                return newCon(C_Bool, conVal(arg1) <= conVal(arg2));
            }
            else if(opn == O_NEq) {
                return newCon(C_Bool, conVal(arg1) != conVal(arg2));
            }
            else if(opn == O_Gtr) {
                return newCon(C_Bool, conVal(arg1) > conVal(arg2));
            }
            else if(opn == O_GtE) {
                return newCon(C_Bool, conVal(arg1) >= conVal(arg2));
            }
            else if(opn == O_Xor) {
                return newCon(C_Bool, (!conVal(arg1)) != (!conVal(arg2)));
            }
            else if(opn == O_And) {
                return newCon(C_Bool, conVal(arg1) && conVal(arg2));
            }
            else if(opn == O_Or ) {
                return newCon(C_Bool, conVal(arg1) || conVal(arg2));
            }
            else {
                printf("Error reducing binary operation - unrecognised "
                        "operation\n");
                assert(false);
            }
        }
    }
    // End of binary operations case

    // iszero & not unary operations
    else if(isApp(exp)
            && isOpn(appFun(exp))
            && (opnType(appFun(exp)) == O_Not
            || opnType(appFun(exp)) == O_IsZ)) {

        OpTy opn = opnType(appFun(exp));
        Exp *arg = appArg(exp);

        if(isApp(arg) || isAbs(arg) || isVar(arg) || isOpn(arg)) {
            return newApp(newOpn(opn), reduceTemplate(arg));
        }
        else {
            if(opn == O_Not)  {
                return newCon(C_Bool, !(conVal(arg)));
            }
            else {
                assert(opn == O_IsZ);
                return newCon(C_Bool, conVal(arg) == 0);
            }
        }
    }
    // End iszero & not unary operations case

    // Polymorphic unary operations
    // Null
    else if(isApp(exp)
            && isOpn(appFun(exp))
            && (opnType(appFun(exp)) == O_Null)) {

        Exp *arg = appArg(exp);
        Exp *reducedArg = reduceTemplateNorm(arg);

        if(isOpn(reducedArg) && (opnType(reducedArg) == O_Empty)) {
            freeExp(reducedArg);
            return newCon(C_Bool, true);
        }
        else {
            freeExp(reducedArg);
            return newCon(C_Bool, false);
        }
    }
    // End Null

    // Head and Tail
    else if(isApp(exp)
            && isOpn(appFun(exp))
            && ((opnType(appFun(exp)) == O_Head)
            || (opnType(appFun(exp)) == O_Tail))) {

        OpTy opn = opnType(appFun(exp));
        Exp *arg = appArg(exp);

        if(isApp(arg)
                && isApp(appFun(arg))
                && isOpn(appFun(appFun(arg)))
                && (opnType(appFun(appFun(arg)))) == O_Cons) {
            
            Exp *head = appArg(appFun(arg));
            Exp *tail = appArg(arg);

            if(opn == O_Head) {
                return copyExp(head);
            }
            else {
                assert(opn == O_Tail);
                return copyExp(tail);
            }
        }
        else {
            return newApp(newOpn(opn), reduceTemplate(arg));
        }
    }
    // End Head and Tail

    // Cons
    else if(isApp(exp)
            && isOpn(appFun(exp))
            && (opnType(appFun(exp)) == O_Cons)) {

        Exp *consArg = appArg(exp);

        return newApp(newOpn(O_Cons), reduceTemplate(consArg));
    }
    // End Cons
    
    // Sum operations
    else if(isApp(exp)
            && isOpn(appFun(exp))
            && ((opnType(appFun(exp)) == O_RemL)
            || (opnType(appFun(exp)) == O_RemR))) {

        OpTy opn = opnType(appFun(exp));
        Exp *arg = appArg(exp);

        if(isApp(arg)
                && isOpn(appFun(arg))
                && ((opnType(appFun(arg)) == O_InjL)
                || (opnType(appFun(arg)) == O_InjR))) {

            OpTy innerOpn = opnType(appFun(arg));
            Exp *innerArg = appArg(arg);

            if(((opn == O_RemL) && (innerOpn == O_InjL))
                    || ((opn == O_RemR) && (innerOpn == O_InjR))) {
                
                return copyExp(innerArg);
            }
            else {
                printf("Error - removed value from a non-sum expression or "
                        "wrong side of sum expression\n");
                assert(false);
            }
        }
        else {
            return newApp(newOpn(opn), reduceTemplate(arg));
        }
    }
    else if(isApp(exp)
            && isOpn(appFun(exp))
            && ((opnType(appFun(exp)) == O_InjL)
            || (opnType(appFun(exp)) == O_InjR))) {

        OpTy opn = opnType(appFun(exp));
        Exp *arg = appArg(exp);

        return newApp(newOpn(opn), reduceTemplate(arg));
    }
    else if(isApp(exp)
            && isOpn(appFun(exp))
            && (opnType(appFun(exp)) == O_IsLeft)) {

        Exp *arg = appArg(exp);

        if(isApp(arg)
                && isOpn(appFun(arg))
                && ((opnType(appFun(arg)) == O_InjL)
                || (opnType(appFun(arg)) == O_InjR))) {

            OpTy injOpn = opnType(appFun(arg));
            return newCon(C_Bool, injOpn == O_InjL);
        }
        else {
            return newApp(newOpn(O_IsLeft), reduceTemplate(arg));
        }
    }
    // End sum operations
    
    // Tuple operations
    else if(isApp(exp)
            && isOpn(appFun(exp))
            && ((opnType(appFun(exp)) == O_Fst)
            || (opnType(appFun(exp)) == O_Snd))) {

        OpTy opn = opnType(appFun(exp));
        Exp *arg = appArg(exp);

        if(isApp(arg)
                && isApp(appFun(arg))
                && isOpn(appFun(appFun(arg)))
                && (opnType(appFun(appFun(arg))) == O_Tuple)) {

            Exp *fst = appArg(appFun(arg));
            Exp *snd = appArg(arg);

            return copyExp((opn == O_Fst) ? fst : snd);
        }
        else {
            return newApp(newOpn(opn), reduceTemplate(arg));
        }
    }
    else if(isApp(exp)
            && isOpn(appFun(exp))
            && (opnType(appFun(exp)) == O_Tuple)) {

        Exp *arg = appArg(exp);

        return newApp(newOpn(O_Tuple), reduceTemplate(arg));
    }
    // End Tuple operations

    // Fixed point combinator
    else if(isApp(exp)
            && isOpn(appFun(exp))
            && (opnType(appFun(exp)) == O_Fix)) {

        return newApp(copyExp(appArg(exp)), copyExp(exp));
    }
    // End fixed point combinator
    // End polymorphic unary operations

    // Lambda abstractions
    else if(isApp(exp)
            && isAbs(appFun(exp))) {

        Exp *abs = appFun(exp);
        Exp *arg = appArg(exp);

        return replace(absBody(abs), 0, arg);
    }
    // End lambda abstractions

    // Function calls
    else if(isApp(exp)
            && isVar(appFun(exp))) {

        Exp *var = appFun(exp);
        Exp *arg = appArg(exp);
        int bind = varBind(var);

        if(hasFunc(bind)) {
            return newApp(instantiate(bind), copyExp(arg));
        }
        else {
            return newApp(copyExp(var), reduceTemplate(arg));
        }
    }
    else if(isVar(exp)
            && hasFunc(varBind(exp))) {

        return instantiate(varBind(exp));
    }
    // End function calls

    // Catch-all application case
    else if(isApp(exp)) {
        Exp *fun = appFun(exp);
        Exp *arg = appArg(exp);

        return newApp(reduceTemplate(fun), reduceTemplate(arg));
    }
    // End catch-all application case

    // If there are no reductions to make, return a copy of the given template.
    else {
        return copyExp(exp);
    }
}