예제 #1
0
        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);
        }
예제 #2
0
        /********************/

        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);
        }
예제 #3
0
        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);
        }
예제 #4
0
        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);
        }
예제 #5
0
        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]
예제 #6
0
        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);
        }