Beispiel #1
0
def handle_call(name, actual_arglist):
    '''
    handle calls for both call statements and call expressions.
    '''
    # unpack the funval and type tuples
    (FUNVAL, type, formal_arglist, body, context) = symtab.lookup_sym(name)
    (FUNCTION_TYPE, ret_type, arg_types) = type

    # set up the environment for static scoping and then execute the function
    actual_val_args = eval_actual_args(actual_arglist)
    save_symtab = symtab.get_config()
    symtab.set_config(context)
    symtab.push_scope(ret_type)
    declare_formal_args(formal_arglist, actual_val_args)

    # execute function
    return_value = None
    try:
        walk(body)
    except ReturnValue as val:
        return_value = val.value

    # NOTE: popping the function scope is not necessary because we
    # are restoring the original symtab configuration
    symtab.set_config(save_symtab)

    return return_value
def id_exp(node):

    (ID, name) = node

    val = symtab.lookup_sym(name)

    return val
Beispiel #3
0
def update_storable(storable, exp):
    '''
    Update a storable location with the value of exp. We have three cases
    to contend with:
       (a) a[i] = v # where a is an array and v is a scalar
       (b) x = v    # where x and v are scalars
       (c) a = b    # where a and b are arrays
    The function 'location' distinguishes between the case (a) and the
    other two cases. Case (a) maps into 'MEMORY' and the other two
    cases map into 'ID'.  Cases (b) and (c) are then distinguished
    when trying to do the actual assignment.
    '''

    # evaluate source
    (t, v) = walk(exp)

    # get information about target
    (LOCATION, location_type, offset) = location(storable)

    if location_type[0] == 'MEMORY':
        # we are copying a value into a single element, e.g.
        #   a[i] = x
        (MEMORY, (tmemory, memory)) = location_type
        (ARRAY_TYPE, base_type, (SIZE, size)) = tmemory

        if offset[1] < 0 or offset[1] > size - 1:
            raise ValueError("array index {}[{}] out of bounds".format(
                name, offset))
        # update memory location of array
        memory[offset[1]] = v
    elif location_type[0] == 'ID':
        # we are copying value(s) based on name, e.g.
        #     a = x
        (ID, name) = location_type
        val = symtab.lookup_sym(name)
        if val[0] == 'CONST':
            # id refers to a scalar, copy scalar value
            (CONST, ts, (VALUE, value)) = val
            symtab.update_sym(name, ('CONST', ts, ('VALUE', coerce(ts, t)(v))))
        elif val[0] == 'ARRAYVAL':
            # id refers to an array, copy the whole array
            (ARRAYVAL, ts, (LIST, smemory)) = val
            # we are copying the whole array
            # Note: we don't want to lose the reference to our memory
            # so we are copying each element separately
            (ARRAY_TYPE, base_type, (SIZE, size)) = ts
            # Note: we could use Python shallow array copy here but
            # this makes it explicit that we are copying elements.
            # we CANNOT copy Python list reference because then both
            # arrays in Cuppa5 would share the same memory.
            for i in range(size):
                smemory[i] = v[i]
        else:
            raise ValueError("internal error on {}".format(val))
    else:
        raise ValueError("internal error on {}".format(location_type))
def call_exp(node):

    (CALLEXP, (ID, name), actual_args) = node

    type = symtab.lookup_sym(name)

    if type[0] != 'FUNCTION_TYPE':
        raise ValueError("{} is not a function".format(name))

    return check_call(type, actual_args)
Beispiel #5
0
def id_exp(node):

    (ID, name) = node
    (symtabrec_type, type, (val_type, value)) = symtab.lookup_sym(name)

    return (type, value)