TypeSpec
ASTternary_expression::typecheck (TypeSpec expected)
{
    // FIXME - closures
    TypeSpec c = typecheck_list (cond(), TypeDesc::TypeInt);
    TypeSpec t = typecheck_list (trueexpr(), expected);
    TypeSpec f = typecheck_list (falseexpr(), expected);

    if (c.is_closure())
        error ("Cannot use a closure as a condition");
    if (c.is_structure())
        error ("Cannot use a struct as a condition");
    if (c.is_array())
        error ("Cannot use an array as a condition");

    // No arrays
    if (t.is_array() || t.is_array()) {
        error ("Not allowed: '%s ? %s : %s'",
               type_c_str(c), type_c_str(t), type_c_str(f));
        return TypeSpec ();
    }

    // The true and false clauses need to be equivalent types, or one
    // needs to be assignable to the other (so one can be upcast).
    if (assignable (t, f) || assignable (f, t))
        m_typespec = higherprecision (t.simpletype(), f.simpletype());
    else
        error ("Not allowed: '%s ? %s : %s'",
               type_c_str(c), type_c_str(t), type_c_str(f));

    return m_typespec;
}
Beispiel #2
0
int asgn_op ( )
{
    descriptor *src;
    descriptor *dest;
    int		status;


    src  = pop ( );
    dest = top ( );
    src  = deref (src);


    if (!assignable (dest)) {
	TypeError ("cannot assign to", NULL, dest, NULL, F_False);
	RecycleData (src);
	return 1;
    }

    dest = deref (dest);
    src = CollapseMatrix (src);
    status = AssignData (dest, &src);
    RecycleData (src);
    D_Temp (dest) = F_False;

    return status;
}
void
ASTvariable_declaration::typecheck_initlist (ref init, TypeSpec type,
                                             const char *name)
{
    // Loop over a list of initializers (it's just 1 if not an array)...
    for (int i = 0;  init;  init = init->next(), ++i) {
        // Check for too many initializers for an array
        if (type.is_array() && i > type.arraylength()) {
            error ("Too many initializers for a '%s'", type_c_str(type));
            break;
        }
        // Special case: ok to assign a literal 0 to a closure to
        // initialize it.
        if (type.is_closure() && ! init->typespec().is_closure() &&
              init->typespec().is_int_or_float() &&
              init->nodetype() == literal_node &&
            ((ASTliteral *)init.get())->floatval() == 0.0f) {
            continue;  // it's ok
        }
        if (! type.is_array() && i > 0)
            error ("Can't assign array initializers to non-array %s %s",
                   type_c_str(type), name);
        if (! assignable(type.elementtype(), init->typespec()))
            error ("Can't assign '%s' to %s %s", type_c_str(init->typespec()),
                   type_c_str(type), name);
    }
}
Beispiel #4
0
unsigned int RFSMasmt::isAssignable()
{
	unsigned int lt = m_lValue->getType();
	unsigned int rt = m_rValue->getType();

	return assignable(lt,rt);
}
bool
ASTNode::check_arglist (const char *funcname, ASTNode::ref arg,
                        const char *formals, bool coerce)
{
    // std::cerr << "ca " << funcname << " formals='" << formals << "\n";
    for ( ;  arg;  arg = arg->next()) {
        if (! *formals)   // More formal args, but no more actual args
            return false;
        if (*formals == '*')  // Will match anything left
            return true;
        if (*formals == '.') {  // Special case for token/value pairs
            // FIXME -- require that the tokens be string literals
            if (arg->typespec().is_string() && arg->next() != NULL) {
                arg = arg->next();
                continue;
            }
            return false;
        }
        if (*formals == '?') {
            if (formals[1] == '[' && formals[2] == ']') {
                // Any array
                formals += 3;
                if (arg->typespec().is_array())
                    continue;  // match
                else return false;  // wanted an array, didn't get one
            }
            if (arg->typespec().is_array())
                return false;   // wanted any scalar, got an array
            formals += 1;
            continue;  // match anything
        }

        TypeSpec argtype = arg->typespec();
        int advance;
        TypeSpec formaltype = m_compiler->type_from_code (formals, &advance);
        formals += advance;
        // std::cerr << "\targ is " << argtype.string() 
        //           << ", formal is " << formaltype.string() << "\n";
        if (argtype == formaltype)
            continue;   // ok, move on to next arg
        if (coerce && assignable (formaltype, argtype))
            continue;
        // Allow a fixed-length array match to a formal array with
        // unspecified length, if the element types are the same.
        if (formaltype.arraylength() < 0 && argtype.arraylength() &&
              formaltype.elementtype() == argtype.elementtype())
            continue;

        // anything that gets this far we don't consider a match
        return false;
    }
    if (*formals && *formals != '*' && *formals != '.') 
        return false;  // Non-*, non-... formals expected, no more actuals

    return true;  // Is this safe?
}
Beispiel #6
0
void SemanticsVisitor::visit(AssigningNode& assign) {
	LHSSemanticsVisitor lhsVisitor(&currentSymbolTable(), errorLog());
	assign.getTargetName()->accept(lhsVisitor);
	assign.getValueExpr()->accept(*this);
	if ( assignable( assign.getTargetName()->getType(), assign.getValueExpr()->getType() ) ) {
		assign.setType( assign.getTargetName()->getType() );
	} else {
		errorLog() << "Right hand side expression not assignable to left hand side name at " << &assign << "\n";
		assign.setType(0); // NOTICE by design, null attribute and error type is 0.
	}
}
TypeSpec
ASTvariable_declaration::typecheck_struct_initializers (ref init)
{
    ASSERT (m_typespec.is_structure());

    if (! init->next() && init->typespec() == m_typespec) {
        // Special case: just one initializer, it's a whole struct of
        // the right type.
        return m_typespec;
    }

    // General case -- per-field initializers

    const StructSpec *structspec (m_typespec.structspec());
    int numfields = (int)structspec->numfields();
    for (int i = 0;  init;  init = init->next(), ++i) {
        if (i >= numfields) {
            error ("Too many initializers for '%s %s'",
                   type_c_str(m_typespec), m_name.c_str());
            break;
        }
        const StructSpec::FieldSpec &field (structspec->field(i));

        if (init->nodetype() == compound_initializer_node) {
            // Initializer is itself a compound, it ought to be initializing
            // a field that is an array.
            if (field.type.is_array ()) {
                ustring fieldname = ustring::format ("%s.%s", m_sym->name().c_str(),
                                                     field.name.c_str());
                typecheck_initlist (((ASTcompound_initializer *)init.get())->initlist(),
                                    field.type, fieldname.c_str());
            } else {
                error ("Can't use '{...}' for a struct field that is not an array");
            }
            continue;
        }

        // Ok to assign a literal 0 to a closure to initialize it.
        if (field.type.is_closure() && ! init->typespec().is_closure() &&
            (init->typespec().is_float() || init->typespec().is_int()) &&
            init->nodetype() == literal_node &&
            ((ASTliteral *)init.get())->floatval() == 0.0f) {
            continue;  // it's ok
        }

        // Normal initializer, normal field.
        if (! assignable(field.type, init->typespec()))
            error ("Can't assign '%s' to '%s %s.%s'",
                   type_c_str(init->typespec()),
                   type_c_str(field.type), m_name.c_str(), field.name.c_str());
    }
    return m_typespec;
}
TypeSpec
ASTtypecast_expression::typecheck (TypeSpec expected)
{
    // FIXME - closures
    typecheck_children (m_typespec);
    TypeSpec t = expr()->typespec();
    if (! assignable (m_typespec, t) &&
        ! (m_typespec.is_int() && t.is_float()) && // (int)float is ok
        ! (m_typespec.is_triple() && t.is_triple()))
        error ("Cannot cast '%s' to '%s'", type_c_str(t),
               type_c_str(m_typespec));
    return m_typespec;
}
TypeSpec
ASTassign_expression::typecheck (TypeSpec expected)
{
    TypeSpec vt = var()->typecheck ();
    TypeSpec et = expr()->typecheck (vt);

    if (! var()->is_lvalue()) {
        error ("Can't assign via %s to something that isn't an lvalue", opname());
        return TypeSpec();
    }

    ASSERT (m_op == Assign);  // all else handled by binary_op

    // We don't currently support assignment of whole arrays
    if (vt.is_array() || et.is_array()) {
        error ("Can't assign entire arrays");
        return TypeSpec();
    }

    // Special case: ok to assign a literal 0 to a closure to
    // initialize it.
    if (vt.is_closure() && ! et.is_closure() &&
        (et.is_float() || et.is_int()) &&
        expr()->nodetype() == literal_node &&
        ((ASTliteral *)&(*expr()))->floatval() == 0.0f) {
        return TypeSpec(); // it's ok
    }

    // If either argument is a structure, they better both be the same
    // exact kind of structure.
    if (vt.is_structure() || et.is_structure()) {
        int vts = vt.structure(), ets = et.structure();
        if (vts == ets)
            return m_typespec = vt;
        // Otherwise, a structure mismatch
        error ("Cannot assign '%s' to '%s'", type_c_str(et), type_c_str(vt));
        return TypeSpec();
    }

    // Expression must be of a type assignable to the lvalue
    if (! assignable (vt, et)) {
        error ("Cannot assign '%s' to '%s'", type_c_str(et), type_c_str(vt));
        // FIXME - can we print the variable in question?
        return TypeSpec();
    }

    return m_typespec = vt;
}
Beispiel #10
0
void SemanticsVisitor::visit(ReturningNode& rn) {
	if (rn.getReturnVal() != 0) { // NOTICE use errorType
		rn.getReturnVal()->accept(*this); // the same as visitChildren
		if (getCurrentFunction() == 0)
			errorLog() << "Return statement can only appear in a function.\n";
		else {
			if(!assignable(getCurrentFunction()->getReturnType()->getType(),
					rn.getReturnVal()->getType())) {
				errorLog() << "Illigal return type.\n";
			}
		}
	} else if (getCurrentFunction() != 0 &&
			!dynamic_cast<VoidTypeDescriptor*>(getCurrentFunction()->getReturnType()->getType()) // return type =/= void
			) {
		errorLog() << "A value must be returned.\n";
	}
}
expected<strong_actor_ptr>
actor_system::dyn_spawn_impl(const std::string& name, message& args,
                             execution_unit* ctx, bool check_interface,
                             optional<const mpi&> expected_ifs) {
  CAF_LOG_TRACE(CAF_ARG(name) << CAF_ARG(args) << CAF_ARG(check_interface)
                << CAF_ARG(expected_ifs));
  if (name.empty())
    return sec::invalid_argument;
  auto& fs = cfg_.actor_factories;
  auto i = fs.find(name);
  if (i == fs.end())
    return sec::unknown_type;
  actor_config cfg{ctx ? ctx : &dummy_execution_unit_};
  auto res = i->second(cfg, args);
  if (!res.first)
    return sec::cannot_spawn_actor_from_arguments;
  if (check_interface && !assignable(res.second, *expected_ifs))
    return sec::unexpected_actor_messaging_interface;
  return std::move(res.first);
}
TypeSpec
ASTreturn_statement::typecheck (TypeSpec expected)
{
    FunctionSymbol *myfunc = oslcompiler->current_function ();
    if (myfunc) {
        // If it's a user function (as opposed to a main shader body)...
        if (expr()) {
            // If we are returning a value, it must be assignable to the
            // kind of type the function actually returns.  This check
            // will also catch returning a value from a void function.
            TypeSpec et = expr()->typecheck (myfunc->typespec());
            if (! assignable (myfunc->typespec(), et)) {
                error ("Cannot return a '%s' from '%s %s()'",
                       type_c_str(et), type_c_str(myfunc->typespec()),
                       myfunc->name().c_str());
            }
        } else {
            // If we are not returning a value, it must be a void function.
            if (! myfunc->typespec().is_void ())
                error ("You must return a '%s' from function '%s'",
                       type_c_str(myfunc->typespec()),
                       myfunc->name().c_str());
        }
        // If the function has other statements AFTER 'return', or if
        // the return statement is in a conditional, we'll need to
        // handle it specially when generating code.
        myfunc->complex_return (this->nextptr() != NULL ||
                                myfunc->nesting_level() > 0);
    } else {
        // We're not part of any user function, so this 'return' must 
        // be from the main shader body.  That's fine (it's equivalent
        // to calling exit()), but it can't return a value.
        if (expr())
            error ("Cannot return a value from a shader body");
    }
    return TypeSpec(); // TODO: what should be returned here?
}
Beispiel #13
0
bool SemanticsVisitor::bindable(TypeDescriptor *dest, TypeDescriptor *src) {
	return assignable(dest, src); // TODO check array type
}
Beispiel #14
0
int gen_op ( )
{
    Matrix	a;
    Matrix	b;
    void       *ptr;
    descriptor *d;
    descriptor *v;
    descriptor *var;
    descriptor *index;
    descriptor *vector;
    descriptor	temp;
    double	value;
    Address	increment;
    Array	arr;
    int		fail;
    unsigned	offset;
    unsigned	i;
    unsigned	c;
    unsigned	r;


    index = ntop (0);
    vector = ntop (1);
    var = ntop (2);

    offset = fetch (pc ++).ival;


    if (D_Type (index) == T_Double) {
        if (!assignable (var)) {
            TypeError ("cannot assign to", NULL, var, NULL, F_False);
            return 1;
        }

        d = &temp;
        D_Type    (d) = T_Null;
        D_Temp    (d) = F_False;
        D_Trapped (d) = F_False;
        D_Pointer (d) = NULL;

        v = CoerceData (vector, T_Double);
        AssignData (d, &v);
        RecycleData (v);
        D_Temp (d) = F_False;

        d_printf ("d = %s %p\n", D_TypeName (d), D_Pointer (d));

        switch (D_Type (d)) {
        case T_Double:
        case T_Matrix:
        case T_Array:
        case T_Null:
            break;


        default:
            TypeError ("cannot index", NULL, d, NULL, F_False);
            return 1;
        }

        *vector = *d;

        D_Type (index) = T_Row;
        D_Row (index) = 0;
    }

    d_printf ("vector = %s %p\n", D_TypeName (vector), D_Pointer (vector));
    var = deref (var);
    fail = F_False;


    switch (D_Type (vector)) {
    case T_Double:
        if (D_Row (index) ++ == 0)
            AssignData (var, &vector);
        else
            fail = F_True;
        break;


    case T_Matrix:
        a = D_Matrix (vector);
        d = &temp;
        D_Temp	  (d) = F_False;
        D_Trapped (d) = F_False;

        if (Mrows (a) == 1) {
            if (++ D_Row (index) <= Mcols (a)) {
                D_Type   (d) = T_Double;
                D_Double (d) = &value;
                value = mdata (a, 1, D_Row (index));
                AssignData (var, &d);
            } else
                fail = F_True;

        } else if (Mcols (a) == 1) {
            if (++ D_Row (index) <= Mrows (a)) {
                D_Type   (d) = T_Double;
                D_Double (d) = &value;
                value = mdata (a, D_Row (index), 1);
                AssignData (var, &d);
            } else
                fail = F_True;

        } else {
            if (++ D_Row (index) <= Mcols (a)) {
                d_printf ("indexing matrix\n");
                r = Mrows (a);
                c = D_Row (index);

                FreeData (var);
                CreateData (var, NULL, NULL, T_Matrix, r, 1);
                D_Temp (var) = F_False;
                b = D_Matrix (var);

                for (i = 1; i <= r; i ++)
                    sdata (b, i, 1) = mdata (a, i, c);
            } else
                fail = F_True;
        }
        break;


    case T_Array:
        arr = D_Array (vector);
        d = &temp;

        if (++ D_Row (index) <= arr -> length) {
            increment = D_Row (index) * arr -> elt_size;
            ptr = (void *) ((char *) arr -> ptr + increment);

            D_Type    (d) = arr -> type;
            D_Temp    (d) = F_False;
            D_Trapped (d) = F_False;
            D_Pointer (d) = ptr;
            AssignData (var, &d);
        } else
            fail = F_True;
        break;


    case T_Null:
        fail = F_True;
        break;
    }


    /* After assignment the variable is certainly not temporary.  Its trapped
       status remains as before: if it was trapped then AssignData() called
       the trap handler which didn't change the status.  If it wasn't then
       AssignData() left the status alone. */

    D_Temp (var) = F_False;

    if (fail == F_True) {
        pop ( );
        FreeData (pop ( ));		/* free the privately owned vector */
        pop ( );

        d = push ( );
        D_Type	  (d) = T_Null;
        D_Temp	  (d) = F_False;
        D_Trapped (d) = F_False;
        D_Pointer (d) = NULL;

        pc += offset;
        d_printf ("failing\n");
    }

    return 0;
}
 bool assignable(const std::set<std::string>& xs) const {
   return assignable(xs, message_types<T>());
 }