// ***** BEGIN LICENSE BLOCK ***** 
// Version: MPL 1.1/GPL 2.0/LGPL 2.1 
//
// The contents of this file are subject to the Mozilla Public License Version 1.1 (the 
// "License"); you may not use this file except in compliance with the License. You may obtain 
// a copy of the License at http://www.mozilla.org/MPL/ 
//
// Software distributed under the License is distributed on an "AS IS" basis, WITHOUT 
// WARRANTY OF ANY KIND, either express or implied. See the License for the specific 
// language governing rights and limitations under the License. 
//
// The Original Code is [Open Source Virtual Machine.] 
//
// The Initial Developer of the Original Code is Adobe System Incorporated.  Portions created 
// by the Initial Developer are Copyright (C)[ #YEARS# ] Adobe Systems Incorporated. All Rights 
// Reserved. 
//
// Contributor(s): Adobe AS3 Team
//
// Alternatively, the contents of this file may be used under the terms of either the GNU 
// General Public License Version 2 or later (the "GPL"), or the GNU Lesser General Public 
// License Version 2.1 or later (the "LGPL"), in which case the provisions of the GPL or the 
// LGPL are applicable instead of those above. If you wish to allow use of your version of this 
// file only under the terms of either the GPL or the LGPL, and not to allow others to use your 
// version of this file under the terms of the MPL, indicate your decision by deleting provisions 
// above and replace them with the notice and other provisions required by the GPL or the 
// LGPL. If you do not delete the provisions above, a recipient may use your version of this file 
// under the terms of any one of the MPL, the GPL or the LGPL. 
// 
// ***** END LICENSE BLOCK ***** */

// type-only:   interface
// method-only: simple function
// type+method: method w/ activation object, class, instance, package

// todo add varargs, optional

AbcFile {
	U16 minor_version                  // = 0
	U16 major_version                  // = 47
	
	U16 constant_pool_count
	Constant[constant_pool_count] {
		U8 kind
		union {
			kind=1 { // CONSTANT_utf8
				U16 length
				U8[length]
			}
			kind=3 { // CONSTANT_Integer
				S32 value
			}
			kind=6 { // CONSTANT_Double
				U64 doublebits (little endian)
			}
			kind=7 { // CONSTANT_Qname	          
				U16 namespace_index
				U16 name_index
			}
			kind=8 { // CONSTANT_Namespace
				U16 name_index                    // CONSTANT_Utf8 uri (maybe 0)
			}
			kind=9 { // CONSTANT_Multiname	   // Used by OP_getproperty, OP_setproperty
				U16 name_index                    // CONSTANT_Utf8  simple name
				U16 namespaces_count              // (256 may seem like enough, but 64K use to seem like a lot of memory)
				U16 namespaces[namespaces_count]  // CONSTANT_Namespace (0 = public)
			}
		}
	}

	U16 methods_count                  // last method is main program
	MethodInfo[methods_count] {
		U16 param_count
		U16 scope_depth
		U16 max_scope
		U16 ret_type					  // CONSTANT_Multiname, 0=Object
		U16 param_types[param_count]	  // CONSTANT_Multiname, 0=Object
		U16 native_name_index             // 0 = not native
		U8 flags                          // 1=need_arguments, 2=need_activation, 4=need_rest 8=has_optional 16=ignore_rest
		U16 optional_count                // if has_optional
		U16 value_index[optional_count]   // if has_optional
	}
	
	U16 traits_count
	Traits[traits_count] {
	    U16 base                               // multiname of base traits
		U16 count              
		Trait[count] {
			U16 name_index                     // CONSTANT_Multiname
			U8  kind
			union {
				kind=0 { // slot
					U16 slot_id                  // 0=autoassign
					U16 type_index               // CONSTANT_Multiname, 0=Object
					U16 value_index              // CONSTANT or 0 for undefined
				}
				kind=1,2,3 { // method, getter, setter
					U16 disp_id			  // 0=autoassign
					U16 method_info         // method must be parsed already
					U8  attr;			     // 0x01: (1=final,0=virtual), 0x02: (1=override,0=new)
					// ISSUE can we move the attr bits into the tag byte? 
				}
				kind=4 { // class
					U16 slot_id                  // 0=autoassign
					U16 class_info               // class must have been parsed already
				}
				kind=5 { // package
					U16 slot_id                  // 0=autoassign
					U16 name_index               // utf8_index of package name
				}
				kind=6 { // function
					U16 slot_index               // 0=autoassign
					U16 method_info		  // method_info of function residing in this slot
				}
			}
		}
	}

	U16 bodies_count                      // last method is main program
	MethodBody[methods_count] {
		U16 method_info
		U16 max_stack
		U16 max_regs
		U32 code_length
		U8[code_length]
		U16 ex_count
		Exception[ex_count] {
			U32 start                           // Offsets of beginning and
			U32 end                             // end of the try block
			U32 target                          // Target PC to transfer control to (catch)
			U16 type_index                      // Type matched by this exception handler
		}
	}
}

interface: name, traits
    types[name] = traits

function: method, traits, itraits
    traits.call = method
    traits.base = Function
    traits.itraits = itraits
    traits.dynamic = true
    itraits.base = Object
    itraits.init = method
    itraits.dynamic = true

package: name, method, traits
    types[name] = traits
    traits.init = method
    traits.base = Object

program: method, traits
    traits.dynamic = true
    traits.base = Object

class: name, itraits, iinit, ctraits, cinit
    types[name] = itraits
    itraits.base = <given>
    itraits.init = iinit
    ctraits.itraits = itraits
    ctraits.init = cinit
    ctraits.base = Class
    ctraits.call = <downcast>
    
    
code {
    ops[]
    targets[]
    mname[]
    int[]
    double[]
    string[]
    reg[]
    slots[]
    dispids[]
    scopes[]
    imm-ints[]
    switchcounts[]
}