fn add_class(
    globals: &mut HashMap<String, LocalSlot<FuncSlot, VarSlot>>,
    classes: &mut HashMap<String, ClassSlot>,
    classes_debug: &mut HashMap<String, ClassDebug>,
    c: &ClassDef,
) {
    let class_name = &c.name.name;
    let super_name = &c.super_class.name;
    let mut class_slot = classes.get(super_name).unwrap().clone();
    let mut class_debug = classes_debug.get(super_name).unwrap().clone();
    // Add constructor function as global function
    globals.insert(
        class_name.clone(),
        LocalSlot::Func(FuncSlot {
            link_name: class_name.clone(),
            level: 0,
        }),
    );

    for declaration in &c.declarations {
        match declaration {
            Declaration::VarDef(v) => {
                // Allocate slot for attribute
                let source_type = v.value.get_type().clone();
                let target_type = ValueType::from_annotation(&v.var.type_);
                let size = if target_type == *TYPE_INT {
                    4
                } else if target_type == *TYPE_BOOL {
                    1
                } else {
                    8
                };
                class_slot.object_size += (size - class_slot.object_size % size) % size;
                let offset = class_slot.object_size + OBJECT_ATTRIBUTE_OFFSET;
                let name = &v.var.identifier.name;
                class_slot.attributes.insert(
                    name.clone(),
                    AttributeSlot {
                        offset,
                        source_type,
                        target_type,
                        init: v.value.content.clone(),
                    },
                );
                class_slot.object_size += size;

                class_debug.attributes.push(VarDebug {
                    offset: offset as i32,
                    line: v.base().location.start.row,
                    name: name.clone(),
                    var_type: TypeDebug::from_annotation(&v.var.type_),
                });
            }
            Declaration::FuncDef(f) => {
                let method_name = &f.name.name;
                let link_name = class_name.clone() + "." + method_name;
                if let Some(method) = class_slot.methods.get_mut(method_name) {
                    // Override method with new link name
                    method.link_name = link_name;

                    let self_type = TypeDebug::from_annotation(&f.params[0].type_);
                    class_debug
                        .methods
                        .get_mut(&method.offset)
                        .unwrap()
                        .1
                        .params[0] = self_type;
                } else {
                    // Allocate prototype slot for new method
                    let offset = class_slot.prototype_size;
                    class_slot
                        .methods
                        .insert(method_name.clone(), MethodSlot { offset, link_name });
                    class_slot.prototype_size += FUNCTION_POINTER_SIZE;

                    let params = f
                        .params
                        .iter()
                        .map(|tv| TypeDebug::from_annotation(&tv.type_))
                        .collect();
                    let return_type = TypeDebug::from_annotation(&f.return_type);

                    class_debug.methods.insert(
                        offset,
                        (
                            method_name.clone(),
                            MethodDebug {
                                params,
                                return_type,
                            },
                        ),
                    );
                }
            }
            _ => panic!(),
        }
    }
    class_debug.size = class_slot.object_size;
    classes.insert(class_name.clone(), class_slot);
    classes_debug.insert(class_name.clone(), class_debug);
}
// Add class info into environment and debug info
Add class info into environment and debug info
Add class info into environment and debug info
fn add_class(
    globals: &mut HashMap<String, LocalSlot<FuncSlot, VarSlot>>,
    classes: &mut HashMap<String, ClassSlot>,
    classes_debug: &mut HashMap<String, ClassDebug>,
    c: &ClassDef,
) {
    let class_name = &c.name.name;
    let super_name = &c.super_class.name;
    let mut class_slot = classes.get(super_name).unwrap().clone();
    let mut class_debug = classes_debug.get(super_name).unwrap().clone();
    // Add constructor function as global function
    globals.insert(
        class_name.clone(),
        LocalSlot::Func(FuncSlot {
            link_name: class_name.clone(),
            level: 0,
        }),
    );
    for declaration in &c.declarations {
        match declaration {
            Declaration::VarDef(v) => {
                // Allocate slot for attribute
                let source_type = v.value.get_type().clone();
                let target_type = ValueType::from_annotation(&v.var.type_);
                let size = if target_type == *TYPE_INT {
                    4
                } else if target_type == *TYPE_BOOL {
                    1
                } else {
                    8
                };
                class_slot.object_size += (size - class_slot.object_size % size) % size;
                let offset = class_slot.object_size + OBJECT_ATTRIBUTE_OFFSET;
                let name = &v.var.identifier.name;
                class_slot.attributes.insert(
                    name.clone(),
                    AttributeSlot {
                        offset,
                        source_type,
                        target_type,
                        init: v.value.content.clone(),
                    },
                );
                class_slot.object_size += size;
                class_debug.attributes.push(VarDebug {
                    offset: offset as i32,
                    line: v.base().location.start.row,
                    name: name.clone(),
                    var_type: TypeDebug::from_annotation(&v.var.type_),
                });
            }
            Declaration::FuncDef(f) => {
                let method_name = &f.name.name;
                let link_name = class_name.clone() + "." + method_name;
                if let Some(method) = class_slot.methods.get_mut(method_name) {
                    // Override method with new link name
                    method.link_name = link_name;
                    let self_type = TypeDebug::from_annotation(&f.params[0].type_);
                    class_debug
                        .methods
                        .get_mut(&method.offset)
                        .unwrap()
                        .1
                        .params[0] = self_type;
                } else {
                    // Allocate prototype slot for new method
                    let offset = class_slot.prototype_size;
                    class_slot
                        .methods
                        .insert(method_name.clone(), MethodSlot { offset, link_name });
                    class_slot.prototype_size += FUNCTION_POINTER_SIZE;
                    let params = f
                        .params
                        .iter()
                        .map(|tv| TypeDebug::from_annotation(&tv.type_))
                        .collect();
                    let return_type = TypeDebug::from_annotation(&f.return_type);
                    class_debug.methods.insert(
                        offset,
                        (
                            method_name.clone(),
                            MethodDebug {
                                params,
                                return_type,
                            },
                        ),
                    );
                }
            }
            _ => panic!(),
        }
    }
    class_debug.size = class_slot.object_size;
    classes.insert(class_name.clone(), class_slot);
    classes_debug.insert(class_name.clone(), class_debug);
}
fn add_class ( globals : & mut HashMap < String , LocalSlot < FuncSlot , VarSlot > > , classes : & mut HashMap < String , ClassSlot > , classes_debug : & mut HashMap < String , ClassDebug > , c : & ClassDef , ) { let class_name = & c . name . name ; let super_name = & c . super_class . name ; let mut class_slot = classes . get ( super_name ) . unwrap ( ) . clone ( ) ; let mut class_debug = classes_debug . get ( super_name ) . unwrap ( ) . clone ( ) ; // Add constructor function as global function globals . insert ( class_name . clone ( ) , LocalSlot :: Func ( FuncSlot { link_name : class_name . clone ( ) , level : 0 , } ) , ) ; for declaration in & c . declarations { match declaration { Declaration :: VarDef ( v ) => { // Allocate slot for attribute let source_type = v . value . get_type ( ) . clone ( ) ; let target_type = ValueType :: from_annotation ( & v . var . type_ ) ; let size = if target_type == * TYPE_INT { 4 } else if target_type == * TYPE_BOOL { 1 } else { 8 } ; class_slot . object_size += ( size - class_slot . object_size % size ) % size ; let offset = class_slot . object_size + OBJECT_ATTRIBUTE_OFFSET ; let name = & v . var . identifier . name ; class_slot . attributes . insert ( name . clone ( ) , AttributeSlot { offset , source_type , target_type , init : v . value . content . clone ( ) , } , ) ; class_slot . object_size += size ; class_debug . attributes . push ( VarDebug { offset : offset as i32 , line : v . base ( ) . location . start . row , name : name . clone ( ) , var_type : TypeDebug :: from_annotation ( & v . var . type_ ) , } ) ; } Declaration :: FuncDef ( f ) => { let method_name = & f . name . name ; let link_name = class_name . clone ( ) + " " + method_name ; if let Some ( method ) = class_slot . methods . get_mut ( method_name ) { // Override method with new link name method . link_name = link_name ; let self_type = TypeDebug :: from_annotation ( & f . params [ 0 ] . type_ ) ; class_debug . methods . get_mut ( & method . offset ) . unwrap ( ) . 1 . params [ 0 ] = self_type ; } else { // Allocate prototype slot for new method let offset = class_slot . prototype_size ; class_slot . methods . insert ( method_name . clone ( ) , MethodSlot { offset , link_name } ) ; class_slot . prototype_size += FUNCTION_POINTER_SIZE ; let params = f . params . iter ( ) . map ( | tv | TypeDebug :: from_annotation ( & tv . type_ ) ) . collect ( ) ; let return_type = TypeDebug :: from_annotation ( & f . return_type ) ; class_debug . methods . insert ( offset , ( method_name . clone ( ) , MethodDebug { params , return_type , } , ) , ) ; } } _ => panic ! ( ) , } } class_debug . size = class_slot . object_size ; classes . insert ( class_name . clone ( ) , class_slot ) ; classes_debug . insert ( class_name . clone ( ) , class_debug ) ; }
Add class info into environment and debug info
Add class info into environment and debug info
globals
&mut HashMap<String, LocalSlot<FuncSlot, VarSlot>>
classes
&mut HashMap<String, ClassSlot>
classes_debug
&mut HashMap<String, ClassDebug>
c
&ClassDef