Compiler Development Series-Ocelot language 3. Elimination of type names, compiler-ocelot

Source: Internet
Author: User
Tags define function

Compiler Development Series-Ocelot language 3. Elimination of type names, compiler-ocelot

"Type name digestion" refers to type digestion. The Type name is represented by the TypeRef object, and the Type is represented by the Type object. Type name resolution is to convert a TypeRef object to a Type object.

The processing of the TypeResolver class is only to traverse the abstract syntax tree. If TypeRef is found, it is converted to the Type from the leaf node. The difference between types and variables is that there is no nested scope (unique scope), so no
Stack is necessary.
[The ing between the TypeRef object and the Type object is stored in the TypeTable object .]

Type is the Type definition. Struct point {int x; int y ;}; is the type definition.

TypeRef is the type name. Struct point is the Type name. The reason why the Type class and the TypeRef class are specially separated is that the code of this Type can be written and used before the Type definition. That is to say, you can write the following code. Such Code cannot be written in C:

struct s var;struct s {int memb;};

Type name resolution entry:

/* Entry ** // # @ range/resolveProgram {public void resolve (AST ast) {/** first call the defineTypes method, generate a Type object based on the Type defined in the Code and save it to the TypeTable object. The type definition imported through import is also processed here. */DefineTypes (ast. types ();/* traversal of the type and abstract syntax tree. * The defineTypes method does not process TypeRef objects such as the type of struct members. Converting the existing TypeRef in the abstract syntax tree to Type is executed in the following foreach statement. If the two parts are not processed separately, the program will be stuck in an endless loop when processing recursive Type Definitions. Ast. types () -- type definition inside and outside the source file * // # @ range/resolveProgram_core {for (TypeDefinition t: ast. types () {t. accept (this);}/** 2nd foreach statements convert all the remaining TypeRef, such as definitions, global variables, and functions read from outside the file using import to Type. Ast. entities () -- Declaration of variables and functions imported using import, and definition of variables and functions in the source file */for (Entity e: ast. entities () {e. accept (this);}/** the above two for loops traverse all types, variables, and functions defined inside and outside the source file, and convert all the TypeRef objects contained in them to Type objects. *///#@@}}

First, execute defineTypes on ast. types (), that is, StructNode (struct definition), UnionNode (consortium definition), and TypedefNode (User Type Definition:

/* Type declaration. * defineTypes is the method for adding a type definition to a TypeTable object * // # @ range/defineTypes {private void defineTypes (List <TypeDefinition> deftypes) {/** use the foreach statement to retrieve TypeDefinition objects in deftypes one by one, and then def. typeRef () and def. definingType () is associated with typeTable. add the put Method to typeTable. Def. typeRef () returns the TypeRef (type name) of the type to be defined by the TypeDefinition object ). Def. definingType () returns the Type (Type) to be defined by the TypeDefinition object ). */For (TypeDefinition def: deftypes) {/** but if typeTable. if isDefined () is true, the TypeRef already exists. In this case, cancel adding and processing and output the error message. */If (typeTable. isDefined (def. typeRef () {error (def, "duplicated type definition:" + def. typeRef ();} The else {/** TypeDefinition class is an abstract class. The actual generated instance is the subclass StructNode, UnionNode, and TypedefNode of TypeDefinition. StructNode indicates the struct definition, UnionNode indicates the consortium definition, and TypedefNode indicates the typedef statement. StructNode # definingType: public Type definingType () {return new StructType (name (), members (), location ());} call the TypeTable # put method to add the generated StrcutType object to the TypeTable object. The TypeTable object contains a HashMap object, so the TypeTable # put method only needs to call HashMap # put. */TypeTable. put (def. typeRef (), def. definingType ());}}}

Store the names and types of the above three types in typeTable. Note that all basic types are automatically put during typeTable initialization. Then the three visit methods of the first for loop:

    // #@@range/StructNode{    public Void visit(StructNode struct) {        resolveCompositeType(struct);        return null;    }    // #@@}    // #@@range/UnionNode{    public Void visit(UnionNode union) {        resolveCompositeType(union);        return null;    }    // #@@}    // #@@range/TypedefNode{    public Void visit(TypedefNode typedef) {        bindType(typedef.typeNode());        bindType(typedef.realTypeNode());        return null;    }    // #@@}

Next:

Public void resolveCompositeType (CompositeTypeDefinition def) {CompositeType ct = (CompositeType) typeTable. get (def. typeNode (). typeRef (); if (ct = null) {throw new Error ("cannot intern struct/union:" + def. name () ;}for (Slot s: ct. members () {bindType (s. typeNode () ;}}/** first, use the TypeNode # isResolved method to check whether the conversion has been completed. If the conversion has been completed, use return to end the processing immediately. If no conversion exists, use n. typeRef () to retrieve TypeRef from TypeNode, convert typeRef to Type object with typeTable. get, and set the Type object to TypeNode with n. setType. * // # @ Range/bindType {private void bindType (TypeNode n) {if (n. isResolved () return; n. setType (typeTable. get (n. typeRef ()));}

It is also very simple. resolveCompositeType is used to check the types of members of each type. The key class is TypeNode, from which TypeRef (type name) is obtained ), then, use the type name to get the existing type definition from typeTable. Obtain all the member variables of the current type, and then bind the name and definition of the member variables through the bindType method. TypeTable actually serves as a transfer station.

The second for loop is to convert all the remaining TypeRef except the above three types to Type. For example:

/** Resolves the type defined by the variable. * /// # @ range/DefinedVariable {public Void visit (DefinedVariable var) {/** the TypeRef object is basically stored in the TypeNode object. TypeNode is a pair of objects for saving TypeRef and Type. Its purpose is to simplify the code of the TypeResolver class. */BindType (var. typeNode (); if (var. hasInitializer () {visitExpr (var. initializer ();} return null ;}

There are also important function types:

/** Define function types. * /// # @ range/DefinedFunction {public Void visit (DefinedFunction func) {/** in Function Definition, TypeRef exists in the following areas. 1. type of the returned value 2. parameter Type 3. */resolveFunctionHeader (func); visitStmt (func. body (); return null;} the type of the private void resolveFunctionHeader (Function func) {/** resolveFunctionHeader method that is used to process the return value. Func. typeNode () returns the TypeNode object with the returned value Type, and then calls the bindType method to convert the returned value Type from TypeRef to Type. */BindType (func. typeNode ();/** the resolveFunctionHeader method processes the form parameters starting from row 2nd. Use the foreach statement * to traverse func. parameters () and retrieve the Parameter object that represents the Parameter. Use param. typeNode () to retrieve the TypeNode object in the Parameter object and convert TypeRef to Type. */For (Parameter param: func. parameters () {// arrays must be converted to pointers in a function parameter. /** the getParamType method of the TypeTable class is used only when the TypeRef of the form parameter is converted to Type. The difference between the get method and the get method is that the array TypeRef is converted to the Type of the pointer. C Language♭) Is equivalent to the pointer type when the parameter type is an array. */Type t = typeTable. getParamType (param. typeNode (). typeRef (); param. typeNode (). setType (t );}}

First, call the resolveFunctionHeader method. The first line in the resolveFunctionHeader is the return type of the bound function, and then a for loop binds all the parameters of the function. Then call visitStmt (func. body (); bind all types of the function body:

    public Void visit(BlockNode node) {        for (DefinedVariable var : node.variables()) {            var.accept(this);        }        visitStmts(node.stmts());        return null;    }

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.