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; }
/// Return the symbol pointer to the individual field that this /// structselect represents; also set structid to the ID of the /// structure type, and fieldid to the field index within the struct. Symbol * ASTstructselect::find_fieldsym (int &structid, int &fieldid) { if (! lvalue()->typespec().is_structure() && ! lvalue()->typespec().is_structure_array()) { return NULL; } ustring structsymname; TypeSpec structtype; find_structsym (lvalue().get(), structsymname, structtype); structid = structtype.structure(); StructSpec *structspec (structtype.structspec()); fieldid = -1; for (int i = 0; i < (int)structspec->numfields(); ++i) { if (structspec->field(i).name == m_field) { fieldid = i; break; } } if (fieldid < 0) { error ("struct type '%s' does not have a member '%s'", structspec->name().c_str(), m_field.c_str()); return NULL; } const StructSpec::FieldSpec &fieldrec (structspec->field(fieldid)); ustring fieldsymname = ustring::format ("%s.%s", structsymname.c_str(), fieldrec.name.c_str()); Symbol *sym = m_compiler->symtab().find (fieldsymname); return sym; }
std::string OSLCompilerImpl::code_from_type (TypeSpec type) const { std::string out; TypeDesc elem = type.elementtype().simpletype(); if (type.is_structure()) { out = Strutil::format ("S%d", type.structure()); } else if (type.is_closure()) { out = 'C'; } else { if (elem == TypeDesc::TypeInt) out = 'i'; else if (elem == TypeDesc::TypeFloat) out = 'f'; else if (elem == TypeDesc::TypeColor) out = 'c'; else if (elem == TypeDesc::TypePoint) out = 'p'; else if (elem == TypeDesc::TypeVector) out = 'v'; else if (elem == TypeDesc::TypeNormal) out = 'n'; else if (elem == TypeDesc::TypeMatrix) out = 'm'; else if (elem == TypeDesc::TypeString) out = 's'; else if (elem == TypeDesc::NONE) out = 'x'; else ASSERT (0); } if (type.is_array()) { int len = type.arraylength (); if (len > 0) out += Strutil::format ("[%d]", len); else out += "[]"; } return out; }