TypeSpec ASTindex::typecheck (TypeSpec expected) { typecheck_children (); const char *indextype = ""; TypeSpec t = lvalue()->typespec(); if (t.is_structure()) { error ("Cannot use [] indexing on a struct"); return TypeSpec(); } if (t.is_closure()) { error ("Cannot use [] indexing on a closure"); return TypeSpec(); } if (index3()) { if (! t.is_array() && ! t.elementtype().is_matrix()) error ("[][][] only valid for a matrix array"); m_typespec = TypeDesc::FLOAT; } else if (t.is_array()) { indextype = "array"; m_typespec = t.elementtype(); if (index2()) { if (t.aggregate() == TypeDesc::SCALAR) error ("can't use [][] on a simple array"); m_typespec = TypeDesc::FLOAT; } } else if (t.aggregate() == TypeDesc::VEC3) { indextype = "component"; TypeDesc tnew = t.simpletype(); tnew.aggregate = TypeDesc::SCALAR; tnew.vecsemantics = TypeDesc::NOXFORM; m_typespec = tnew; if (index2()) error ("can't use [][] on a %s", type_c_str(t)); } else if (t.aggregate() == TypeDesc::MATRIX44) { indextype = "component"; TypeDesc tnew = t.simpletype(); tnew.aggregate = TypeDesc::SCALAR; tnew.vecsemantics = TypeDesc::NOXFORM; m_typespec = tnew; if (! index2()) error ("must use [][] on a matrix, not just []"); } else { error ("can only use [] indexing for arrays or multi-component types"); return TypeSpec(); } // Make sure the indices (children 1+) are integers for (size_t c = 1; c < nchildren(); ++c) if (! child(c)->typespec().is_int()) error ("%s index must be an integer, not a %s", indextype, type_c_str(index()->typespec())); // If the thing we're indexing is an lvalue, so is the indexed element m_is_lvalue = lvalue()->is_lvalue(); return m_typespec; }
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? }
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); } }
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; }