

#include "Frame.h"
#include "Func.h"
#include <stdio.h>

Frame::Frame(Frame *par) : Obj (FrameType)
{
    alloced = 8;
    size = 0;
    bindings = (struct binding *) malloc(alloced * sizeof(struct binding));
    parent = par;
}

void Frame::AddBinding (Symbol *sym, Value val = nil)
{
    if (size == alloced) {
	alloced <<= 1;
	bindings = (struct binding *) realloc(bindings, alloced * sizeof(struct binding));
    }
    bindings[size].sym = sym;
    bindings[size].val = val;
    size++;
}

void Frame::Dump(void)
{
    int n;
    for (n = 0; n < size; n++) {
	bindings[n].sym->Dump();
	if (n+1 < size) {
	    printf (", ");
	}
    }
}

int Frame::Lookup (Symbol *sym, int *levels, int *offset)
{
    int n;
    if (!this) return 0;
    for (n = 0; n < size; n++) {
	if (bindings[n].sym == sym) {
	    *levels = 0;
	    *offset = n;
	    return 1;
	}
    }
    if (parent->Lookup(sym, levels, offset)) {
	(*levels)++;
	return 1;
    }
    return 0;
}


struct binding *Frame::FindBinding (int levels, int offset)
{
    if (levels) return parent->FindBinding(levels - 1, offset);
    return bindings + offset;
}

Value &Frame::FindValue (int levels, int offset)
{
    return FindBinding(levels, offset)->val;
}
	
Symbol *Frame::FindSymbol (int levels, int offset)
{
    return FindBinding(levels, offset)->sym;
}
	
void Frame::IsArgsFor (Func *func)
{
    Frame *f = func->Prog()->Params();
    int n;
    if (f->size != size) {
	printf ("Wrong number of args\n");
	exit(1);
    }
    for (n = 0; n < size; n++) {
	bindings[n].sym = f->bindings[n].sym;
    }
}
