/* Pattern matching routines */
#include "evalint.h"

pattern *make_pattern(expr)
char *expr;
{
    register pattern *pat;

    if (pat = ALLOC(pattern))
    {
	if (pat->val = compile(expr))
	{
	    init_var_list(&pat->vl);
	    if (make_var_list(pat->val, &pat->vl)) return(pat);
	    free_expr(pat->val);
	}
    }
    return(NULL);
}

void free_pattern(pat)
pattern *pat;
{
    free_expr(pat->val);
    free_var_list(&pat->vl);
    FREE(pattern, pat);
}

/* The actual recursive pattern matcher */
static int _match_pattern(pat, expr)
register value pat;
register value expr;
{
    if (pat->type == var) /* Variable in pattern */
    {
	value val;

	val = get_var(&pat->vr);
	if (val == NULL) /* uninstantiated ==> can be anything */
	{
	    set_var(&pat->vr, expr);
	    return(TRUE);
	}
	else /* instantiated ==> must be the same as last time */
	    return(same(val, expr));
    }
    /* For everything else, an exact match */
    else if (pat->type != expr->type) return(FALSE);
    else
	switch (pat->type)
	{
	    case cste:
		return(pat->cte == expr->cte);
	    case fonc:
		return(pat->fn.func == expr->fn.func &&
		       _match_pattern(pat->fn.arg, expr->fn.arg));
	    case op:
		return(pat->opr.op == expr->opr.op &&
		       _match_pattern(pat->opr.arg1, expr->opr.arg1) &&
		       _match_pattern(pat->opr.arg2, expr->opr.arg2));
	}
}

/* Matches a pattern to a value */
/* returns TRUE if matches, FALSE otherwise */
/* If TRUE, the variables used in the var_list will contain what they matched */
/* Don't forget to free them ! */
int match_pattern(pat, expr)
pattern *pat;
value expr;
{
    /* This makes sure the pattern variables don't interfere with the
      variables used in the expression */
    if (create_vars(&pat->vl))
    {
	if (_match_pattern(pat->val, expr)) return(TRUE);
	free_vars(&pat->vl); /* Not matched, free vars */
    }
    return(FALSE);
}

