public int parse_OBJ_list_ID_contents() { // <OBJ_list_ID_contents> := <ID_list_value> | <ID_list_type> [',' <ID_list_value> ] IArchetypeField arch_field = tmp.new_obj.archetype[tmp.field_name]; int nn; tmp.list_int = new List <int>(); nn = parse_ID_list_value(); if (nn > 0) { // An untyped field, set the expected field type if (arch_field != null) { if (arch_field.type != FieldType.LIST_ID) { back_up_parser(nn); return(0); } tmp.type_of_field = arch_field.type; } else { // It _seems_ that this will never be hit, for the same reasons as the analogous block in parse_OBJ_ID_contents()... tmp.type_of_field = FieldType.LIST_ID; warn_add_OBJ_field_defaulting_to_basic_field_type(tmp.field_name, tmp.new_obj.archetype.tag, FieldType.LIST_ID); } } else { nn = parse_ID_list_type(); if (nn == 0) { return(0); } // A typed field. Type may optionally be followed by a value. nn += accept(TokenType.COMMA); nn += parse_ID_list_value(); } // Check that LIST_ID is the archetype field type, and we're ready to add the Obj field if (arch_field == null) { warn_add_OBJ_field_not_in_archetype(tmp.field_name, tmp.new_obj.archetype.tag); } else if (arch_field.type != tmp.type_of_field) { warn_add_OBJ_field_mismatch_with_archetype_field(tmp.new_obj, tmp.field_name, tmp.type_of_field); tmp.clear_field_data(); return(nn); // We will consume the rest of the declaration syntax, ignoring these contents } tmp.new_obj.add_field(tmp.field_name, tmp.type_of_field); tmp.new_obj[tmp.field_name].ilist = tmp.list_int; print_debug_for_add_list_field(tmp.field_name, tmp.type_of_field, tmp.list_int, null, null); tmp.clear_field_data(); return(nn); }
/********************/ public int parse_OBJ_int_contents() { // <OBJ_int_contents> := <int_value> | <int_type> [',' <int_value> ] IArchetypeField arch_field = tmp.new_obj.archetype[tmp.field_name]; int nn; nn = parse_int_value(); if (nn > 0) { // An untyped field, set the expected field type if (arch_field != null) { // From the archetype, if possible if (arch_field.type != FieldType.INT) { back_up_parser(nn); return(0); } tmp.type_of_field = arch_field.type; } else { // Otherwise we expect INT (and untyped fields intended to be ID or other derived-from-INT are thus consumed) tmp.type_of_field = FieldType.INT; warn_add_OBJ_field_defaulting_to_basic_field_type(tmp.field_name, tmp.new_obj.archetype.tag, FieldType.INT); } } else { nn = parse_int_type(); if (nn == 0) { return(0); } // A typed field. Type may optionally be followed by a value. nn += accept(TokenType.COMMA); nn += parse_int_value(); } // Check that INT is the archetype field type, and we're ready to add the Obj field if (arch_field == null) { warn_add_OBJ_field_not_in_archetype(tmp.field_name, tmp.new_obj.archetype.tag); } else if (arch_field.type != tmp.type_of_field) { warn_add_OBJ_field_mismatch_with_archetype_field(tmp.new_obj, tmp.field_name, tmp.type_of_field); tmp.clear_field_data(); return(nn); // We will consume the rest of the declaration syntax, ignoring these contents } tmp.new_obj.add_field(tmp.field_name, tmp.type_of_field); tmp.new_obj[tmp.field_name].iv = tmp.int_val; //Form1.stdout.print(" OBJ add_field(name={0},type={1},val={2})\n", tmp.field_name, tmp.type_of_field, tmp.int_val); tmp.clear_field_data(); return(nn); }
public int parse_OBJ_list_decimal_contents() { // <OBJ_list_decimal_contents> := <decimal_list_value> | <decimal_list_type> [',' <decimal_list_value>] IArchetypeField arch_field = tmp.new_obj.archetype[tmp.field_name]; int nn; tmp.list_decimal = new List <decimal>(); nn = parse_decimal_list_value(); if (nn > 0) { // An untyped field, set the expected field type if (arch_field != null) { if (arch_field.type != FieldType.LIST_DECIMAL) { back_up_parser(nn); return(0); } tmp.type_of_field = arch_field.type; } else { tmp.type_of_field = FieldType.LIST_DECIMAL; warn_add_OBJ_field_defaulting_to_basic_field_type(tmp.field_name, tmp.new_obj.archetype.tag, FieldType.LIST_DECIMAL); } } else { nn = parse_decimal_list_type(); if (nn == 0) { return(0); } // A typed field. Type may optionally be followed by a value. nn += accept(TokenType.COMMA); nn += parse_decimal_list_value(); } // Check that LIST_DECIMAL is the archetype field type, and we're ready to add the Obj field if (arch_field == null) { warn_add_OBJ_field_not_in_archetype(tmp.field_name, tmp.new_obj.archetype.tag); } else if (arch_field.type != tmp.type_of_field) { warn_add_OBJ_field_mismatch_with_archetype_field(tmp.new_obj, tmp.field_name, tmp.type_of_field); tmp.clear_field_data(); return(nn); // We will consume the rest of the declaration syntax, ignoring these contents } tmp.new_obj.add_field(tmp.field_name, tmp.type_of_field); tmp.new_obj[tmp.field_name].dlist = tmp.list_decimal; print_debug_for_add_list_field(tmp.field_name, tmp.type_of_field, null, null, tmp.list_decimal); tmp.clear_field_data(); return(nn); }
public int parse_OBJ_string_contents() { // <OBJ_string_contents> := <string_value> | <string_type> [',' <string_value> ] IArchetypeField arch_field = tmp.new_obj.archetype[tmp.field_name]; int nn; nn = parse_string_value(); if (nn > 0) { // An untyped field, set the expected field type if (arch_field != null) { if (arch_field.type != FieldType.STRING) { back_up_parser(nn); return(0); } tmp.type_of_field = arch_field.type; } else { tmp.type_of_field = FieldType.STRING; warn_add_OBJ_field_defaulting_to_basic_field_type(tmp.field_name, tmp.new_obj.archetype.tag, FieldType.STRING); } } else { nn = parse_string_type(); if (nn == 0) { return(0); } // A typed field. Type may optionally be followed by a value. nn += accept(TokenType.COMMA); nn += parse_string_value(); } // Check that STRING is the archetype field type, and we're ready to add the Obj field if (arch_field == null) { warn_add_OBJ_field_not_in_archetype(tmp.field_name, tmp.new_obj.archetype.tag); } else if (arch_field.type != tmp.type_of_field) { warn_add_OBJ_field_mismatch_with_archetype_field(tmp.new_obj, tmp.field_name, tmp.type_of_field); tmp.clear_field_data(); return(nn); // We will consume the rest of the declaration syntax, ignoring these contents } tmp.new_obj.add_field(tmp.field_name, tmp.type_of_field); tmp.new_obj[tmp.field_name].sv = tmp.string_val; //Form1.stdout.print(" OBJ add_field(name={0},type={1},val={2})\n", tmp.field_name, tmp.type_of_field, tmp.decimal_val); tmp.clear_field_data(); return(nn); }
public IObjField this[string field_name] { // TODO: 2010/04/08 // Determined that get and set BOTH need to ALWAYS auto-vivify the field. // This is because someobj["some_field"].iv = 42 calls OBJ indexer property GET, and then FIELD property SET on the field that returns. // // In future, maybe some means of avoiding "needless" auto-vivification on get can be found, // but it may be a non-critical optimization anyways -- that needs study to justify optimization effort get { if (field_name == null) { Error.BadArg("Got null field_name"); } if (!Token.is_bare_multi_word(field_name)) { Error.BadArg("Got invalid field_name '{0}'", field_name); } if (!fields.ContainsKey(field_name)) { // If the field is not present, auto-vivify the field from the Archetype's corresponding field IArchetypeField arch_field = archetype[field_name]; if (arch_field == null) { // TODO: Policy control over behavior upon .get of a field not present in the Archetype. // Default will likely be to auto-vivify and return default value? //Form1.stdout.print("ObjField.get: found null archetype field for field_name '{0}', auto-vivifying.\n", field_name); fields[field_name] = new FieldTempNull(this, field_name); // Let's see if the FieldTempNull approach works...wow, surprisingly well at near-first test! // Hmmm...if we don't have an Archetype field to get an IObjField from, how do we know what type to instantiate? // Seems it will have to be fatal? I'd rather be able to auto-vivify, but this gets called _before_ the .set ...argh... //Error.Throw("Somehow got null archetype arch_field for field_name '{0}'", field_name); } else { fields[field_name] = arch_field.default_value; // TODO: Verify that this is a "deep" copy, or deep enough at any rate... } } return(fields[field_name]); } set { if (field_name == null) { Error.BadArg("Got null field_name"); } if (!Token.is_bare_multi_word(field_name)) { Error.BadArg("Got invalid field_name '{0}'", field_name); } if (archetype[field_name] != null) { SemanticTypes type_of_new_field = value.type.semantic_type; SemanticTypes type_of_arch_field = archetype[field_name].type.semantic_type; if (type_of_new_field != type_of_arch_field) { Error.BadArg("ObjField.set: Called for Obj '{0}' with Archetype '{1}' on field_name '{2}', " + "with strange IObjField having semantic type '{3}' " + "which differs from the archetype field semantic type '{4}'", autotag, archetype.tag, field_name, type_of_new_field, type_of_arch_field); } } //else //{ // Form1.stdout.print("Obj.this[].set called for field '{0}', archetype does not contain that field\n", field_name); //} if (fields.ContainsKey(field_name) && fields[field_name].type != FieldType.EMPTY) { // Call to set for an already-present field. // This is OK if the already-present field is a FieldTempNull... ??? // TODO: Should be controlled by a policy variable. // A likely default would be to warn and replace the existing attribute. Error.BadArg("Got already-present Obj parse_field_name '{0}'", field_name); } fields[field_name] = value; } } // this[field_name]
public int parse_OBJ_ID_contents() { // <OBJ_ID_contents> := <ID_value> | <ID_type> [',' <ID_value> ] IArchetypeField arch_field = tmp.new_obj.archetype[tmp.field_name]; int nn; nn = parse_ID_value(); if (nn > 0) { // TODO: // Given that (due to the grammar and the ordering in parse_OBJ_scalar_contents() ) // parse_OBJ_int_contents() will always be called before this method, // under exactly what circumstances will this be called? // // Needs careful thought. For now, handling this like for other types... if (arch_field != null) { if (arch_field.type != FieldType.ID) { back_up_parser(nn); return(0); } tmp.type_of_field = arch_field.type; } else { // It _seems_ that this case will NEVER get hit, // as any (untyped + not-in-archetype fields) would get grabbed by parse_OBJ_int_contents(). // TODO: Review this carefully... tmp.type_of_field = FieldType.ID; warn_add_OBJ_field_defaulting_to_basic_field_type(tmp.field_name, tmp.new_obj.archetype.tag, FieldType.ID); } } else { nn = parse_ID_type(); if (nn == 0) { return(0); } // A typed field. Type may optionally be followed by a value. nn += accept(TokenType.COMMA); nn += parse_ID_value(); } // Check that ID is the archetype field type, and we're ready to add the Obj field if (arch_field == null) { warn_add_OBJ_field_not_in_archetype(tmp.field_name, tmp.new_obj.archetype.tag); } else if (arch_field.type != tmp.type_of_field) { warn_add_OBJ_field_mismatch_with_archetype_field(tmp.new_obj, tmp.field_name, tmp.type_of_field); tmp.clear_field_data(); return(nn); // We will consume the rest of the declaration syntax, ignoring these contents } tmp.new_obj.add_field(tmp.field_name, tmp.type_of_field); tmp.new_obj[tmp.field_name].iv = tmp.int_val; //Form1.stdout.print(" OBJ add_field(name={0},type={1},val={2})\n", tmp.field_name, tmp.type_of_field, tmp.int_val); tmp.clear_field_data(); return(nn); }