Ejemplo n.º 1
0
        public static void EndCompoundStatement(List <CCompoundStatmentItemType> itemTypes)
        {
            CIdentifier.ExitBlockScope();

            List <CStatment> blockBody = new List <CStatment>();

            List <int> localVarSizes = new List <int>();

            //the item types come in sequential order (top to bottom), but they are sitting on the stack in reverse order (botom to top)
            //revers the list to deal with this
            itemTypes.Reverse();
            foreach (var itemType in itemTypes)
            {
                if (itemType == CCompoundStatmentItemType.Statment)
                {
                    CStatment stat = PopStatement();
                    blockBody.Add(stat);
                }
                else
                {
                    CDeclaration decl = CDeclaration.PopDecl();

                    localVarSizes.Add(decl.Size);

                    //get a statments that initilizes the local variable (or does nothing if it is not a definition)
                    blockBody.Add(decl.GetDefinitionStatment());
                }
            }

            //put the statments back in top to bottom order
            blockBody.Reverse();

            PushStatement(new CStatment(blockBody, localVarSizes));
        }
Ejemplo n.º 2
0
        internal static CIdentifier InternString(string p)
        {
            string name = AutoGenerateLabel("internedString");

            var id = new CIdentifier(name, p);

            fileScope[name] = id;
            return(id);
        }
Ejemplo n.º 3
0
        //if statment
        public CStatment(CExpression cExpression, CStatment cStatment)
        {
            string ifBody = CIdentifier.AutoGenerateLabel("ifBody");
            string EndIf  = CIdentifier.AutoGenerateLabel("endIf");

            Add(cExpression);
            Add(new OpCodeEmitter(OpCode.PUSHW, ifBody));
            Add(new OpCodeEmitter(OpCode.JIF));
            Add(new OpCodeEmitter(OpCode.PUSHW, EndIf));
            Add(new OpCodeEmitter(OpCode.JMP));
            Add(new LabelEmitter(ifBody));
            Add(cStatment);
            Add(new LabelEmitter(EndIf));
        }
Ejemplo n.º 4
0
        //exit function scope
        public static void EndFunctionDefinition(int numSpecifiers)
        {
            CIdentifier.ExitFunctionScope();

            List <CDeclarationSpecifier> specs = new List <CDeclarationSpecifier>();

            for (int i = 0; i < numSpecifiers; i++)
            {
                specs.Add(PopDeclSpec());
            }

            CDeclarationSpecifier typeSpec     = specs.First(spec => spec.SpeciferType == CDeclarationSpecifierType.Type);
            CDeclarationSpecifier storageClass = specs.FirstOrDefault(spec => spec.SpeciferType == CDeclarationSpecifierType.Storage);

            CDeclarator paramDecl = PopDeclarator();

            CIdentifier.DefineFunction(paramDecl.TypeModifier.ModifyType(typeSpec.type), paramDecl.Identifer, storageClass == null ? CStorageClass.Ignore : storageClass.StorageClass);
        }
Ejemplo n.º 5
0
        //paramaters

        //define param in function scope or function prototype scope
        public static void ParamaterDeclaration(int numSpecifiers)
        {
            List <CDeclarationSpecifier> specs = new List <CDeclarationSpecifier>();

            for (int i = 0; i < numSpecifiers; i++)
            {
                specs.Add(PopDeclSpec());
            }

            CDeclarationSpecifier typeSpec = specs.First(spec => spec.SpeciferType == CDeclarationSpecifierType.Type);

            //ignore const and register specifiers on params

            CDeclarator declarator = PopDeclarator();

            CParamater param = CIdentifier.CreateFunctionParameter(
                declarator.Identifer,
                declarator.TypeModifier != null ? declarator.TypeModifier.ModifyType(typeSpec.type) : typeSpec.type
                );

            PushParam(param);
        }
Ejemplo n.º 6
0
        internal static CIdentifier CreatLabel(string label)
        {
            CIdentifier lb = new CIdentifier(label);

            if (currentFunctionScope != null)
            {
                if (currentFunctionScope.ContainsKey(label))
                {
                    throw new SemanticException("label " + label + " already exists in this scope");
                }

                currentFunctionScope[label] = lb;
            }
            else
            {
                if (fileScope.ContainsKey(label))
                {
                    throw new SemanticException("label " + label + " already exists in this scope");
                }

                fileScope[label] = lb;
            }
            return(lb);
        }
Ejemplo n.º 7
0
 //parameter list
 //enter function prototype scope
 public static void BeginFunctionDeclarator()
 {
     CIdentifier.EnterFunctionPrototypeScope();
 }
Ejemplo n.º 8
0
        //definitions

        //A definition is a declaration that provides all information about the identifiers it declares.
        //Every declaration of an enum or a typedef is a definition.
        //For functions, a declaration that includes the function body is a function definition:
        //For objects, a declaration that allocates storage (automatic or static, but not extern) is a definition,
        //while a declaration that does not allocate storage (external declaration) is not.
        //For structs, declarations that specify the list of members are definitions:
        //declarations which are not definitions can be repeted. declarations which are definitions cannot be repeted

        //http://en.cppreference.com/w/c/language/function_definition
        //Unlike function declaration, function definitions are allowed at file scope only (there are no nested functions).
        // functions are of the form
        // specifiers-and-qualifiers parameter-list-declarator function-body

        /*
         *  specifiers-and-qualifiers	-	a combination of
         *      type specifiers that, possibly modified by the declarator, form the return type
         *      storage class specifiers, which determine the linkage of the identifier (static, extern, or none)
         *
         *  parameter-list-declarator	-	a declarator for a function type which uses a parameter list to designate function parameters
         *
         *  function-body	-	a compound statement, that is a brace-enclosed sequence of declarations and statements, that is executed whenever this function is called
         *
         * return type of function must be a complete non-array object type or the type void.
         */
        //enter function scope
        public static void BeginFunctionDefinition()
        {
            CIdentifier.EnterFunctionScope();
        }
Ejemplo n.º 9
0
        //storage and linkage
        //http://en.cppreference.com/w/c/language/storage_duration

        /*
         * Every object has a property called storage duration, which limits the object lifetime. There are four kinds of storage duration in C:
         *
         * automatic storage duration.
         * The storage is allocated when the block in which the object was declared is entered and
         * deallocated when it is exited by any means (goto, return, reaching the end). If the block is entered recursively, a new allocation is performed for every recursion level. All function parameters and non-static block-scope objects have this storage duration.
         *
         * static storage duration.
         * The storage duration is the entire execution of the program,
         * and the value stored in the object is initialized only once, prior to main function.
         * All objects declared static and all objects with either internal or external linkage have this storage duration.
         *
         * thread storage duration. NOT SUPPORTED
         *
         * allocated storage duration.
         * The storage is allocated and deallocated on request, using dynamic memory allocation functions.
         *
         * Linkage
         * Linkage refers to the ability of an identifier (variable or function) to be referred to in other scopes.
         * If a variable or function with the same identifier is declared in several scopes,
         * but cannot be referred to from all of them, then several instances of the variable are generated.
         *
         * The following linkages are recognized:
         *
         * no linkage.
         * The identifier can be referred to only from the scope it is in.
         * All function parameters and all non-extern block-scope variables (including the ones declared static) have this linkage.
         *
         * internal linkage.
         * The identifier can be referred to from all scopes in the current translation unit.
         * All static identifiers (both functions and variables) have this linkage.
         *
         * external linkage.
         * The identifier can be referred to from any other translation units in the entire program.
         * All non-static functions, all extern variables (unless earlier declared static), and all file-scope non-static variables have this linkage.
         *
         * Names at file scope that are const and not extern have external linkage in C
         *
         * Storage-class specifiers specify one of the following combinations of storage duration and linkage
         * auto - automatic duration and no linkage (on stack)
         * register - NOT SUPPORTED
         * static - static duration and internal linkage (unless at block scope) (in data or rodata segment)
         * extern - static duration and external linkage (unless already declared internal) (on heap)
         *
         * If no storage-class specifier is provided, the defaults are:
         * extern for all functions
         * extern for objects at file scope
         * auto for objects at block scope
         *
         * For any struct or union declared with a storage-class specifier,
         * the storage duration (but not linkage) applies to their members, recursively.
         *
         * Function declarations at block scope can use extern or none at all.
         * Function declarations at file scope can use extern or static.
         */

        //scope
        //http://en.cppreference.com/w/c/language/scope

        /*Each identifier that appears in a C program is visible (that is, may be used) only in some possibly discontiguous portion of the source code called its scope.
         * Within a scope, an identifier may designate more than one entity only if the entities are in different name spaces.
         * C has four kinds of scopes:
         *  block scope
         *  file scope
         *  function scope
         *  function prototype scope
         *
         * Nested scopes
         * If two different entities named by the same identifier are in scope at the same time,
         * and the scopes are nested,
         * the declaration that appears in the inner scope hides the declaration that appears in the outer scope
         *
         * Block Scope
         * The scope of any identifier declared inside a compound statement,
         * including function bodies,
         * or in any expression, declaration, or statement appearing in
         * if, switch, for, while, or do-while statement,
         * or within the parameter list of a function definition
         * begins at the point of declaration and ends at the end of the block or statement in which it was declared.
         *
         * File scope
         * The scope of any identifier declared outside of any block or parameter list begins at the point of declaration and ends at the end of the translation unit (file).
         * File-scope identifiers have external linkage and static storage duration by default.
         *
         * Function scope
         * A label (and only a label) declared inside a function is in scope everywhere in that function, in all nested blocks, before and after its own declaration.
         *
         * Function prototype scope
         * The scope of a name introduced in the parameter list of a function declaration ends at the end of the function declarator.
         */

        //declarations
        //http://en.cppreference.com/w/c/language/declarations
        //A declaration is a C language construct that introduces one or more identifiers into the program and specifies their meaning and properties.
        //Declarations may appear in any scope. Each declaration ends with a semicolon (just like a statement) and consists of two distinct parts:

        /*
         * specifiers-and-qualifiers	-	whitespace-separated list of, in any order,
         *  exactly one type specifier:
         *      void
         *      the name of an arithmetic type
         *      the name of an atomic type
         *      a name earlier introduced by a typedef declaration
         *      struct, union, or enum specifier
         *  zero or one storage-class specifiers:
         *      typedef,
         *      auto,
         *      static,
         *      extern
         *  optional const
         *
         *  declarators-and-initializers	-	comma-separated list of declarators
         *  (each declarator provides additional type information and/or the identifier to declare).
         *  Declarators may be accompanied by initializers.
         */
        public static void Declaration(int numSpecifier, int numDeclarators)
        {
            List <CDeclarationSpecifier> specifiers = new List <CDeclarationSpecifier>();

            for (int i = 0; i < numSpecifier; i++)
            {
                specifiers.Add(PopDeclSpec());
            }

            //TODO hanldle unsigned, signed, long, typedef name
            IEnumerable <CDeclarationSpecifier> typeSpecs = specifiers.Where(spec => spec.SpeciferType == CDeclarationSpecifierType.Type);

            CType resolvedType = CType.ResolveTypeFromSpecifers(typeSpecs);

            IEnumerable <CDeclarationSpecifier> typeDefNames = specifiers.Where(spec => spec.SpeciferType == CDeclarationSpecifierType.Name);

            CDeclarationSpecifier storageClass   = specifiers.FirstOrDefault(spec => spec.SpeciferType == CDeclarationSpecifierType.Storage);
            CDeclarationSpecifier constQualifier = specifiers.FirstOrDefault(spec => spec.SpeciferType == CDeclarationSpecifierType.Const);

            List <CDeclarator> declarators = new List <CDeclarator>();

            for (int i = 0; i < numDeclarators; i++)
            {
                declarators.Add(PopDeclarator());
            }

            List <CIdentifier> declared = new List <CIdentifier>();

            foreach (CDeclarator declarator in declarators)
            {
                CIdentifier id = CIdentifier.CreateIdentifierInCurrentScope(declarator.Identifer, declarator.TypeModifier != null ?  declarator.TypeModifier.ModifyType(resolvedType) : resolvedType, storageClass == null ? CStorageClass.Ignore : storageClass.StorageClass, constQualifier == null ? CConstType.Ignore : constQualifier.ConstType);

                if (declarator.Init != null)
                {
                    id.Init = declarator.Init;
                }

                declared.Add(id);
            }

            if (declared.Count == 0)
            {
                if (storageClass != null && storageClass.StorageClass == CStorageClass.Typedef)
                {
                    //this is a typedef
                    foreach (var defSpec in typeDefNames)
                    {
                        CType.TypeDef(defSpec.name, resolvedType);
                    }
                }
                else
                {
                    //this is a declaration without a declarator
                    var name = typeDefNames.First();

                    CIdentifier id = CIdentifier.CreateIdentifierInCurrentScope(name.name, resolvedType, storageClass == null ? CStorageClass.Ignore : storageClass.StorageClass, constQualifier == null ? CConstType.Ignore : constQualifier.ConstType);

                    declared.Add(id);
                }
            }

            PushDecl(new CDeclaration(declared));
        }
Ejemplo n.º 10
0
        //http://en.cppreference.com/w/c/language/goto
        // Transfers control unconditionally to the desired location defined by a label.
        // goto label ;
        public static void GotoStatement(string label)
        {
            CIdentifier id = CIdentifier.IdentifierFromNameInCurrentScope(label);

            PushStatement(new CStatment(id));
        }
Ejemplo n.º 11
0
 private static void EnterLoop()
 {
     loopChechLabels.Push(CIdentifier.CreatLabel(CIdentifier.AutoGenerateLabel("LoopCheck")));
     loopBodyLabels.Push(CIdentifier.CreatLabel(CIdentifier.AutoGenerateLabel("LoopBody")));
     endLoopLabels.Push(CIdentifier.CreatLabel(CIdentifier.AutoGenerateLabel("EndLoop")));
 }
Ejemplo n.º 12
0
 //A compound statement, or block, is a brace-enclosed sequence of statements and declarations.
 //The compound statement allows a set of declarations and statements to be grouped into one unit that can be used
 // anywhere a single statement is expected (for example, in an if statement or an iteration statement)
 //Each compound statement introduces its own block scope.
 //http://en.cppreference.com/w/c/language/scope
 public static void BeginCompoundStatement()
 {
     CIdentifier.EnterBlockScope();
 }
Ejemplo n.º 13
0
 //goto statment
 public CStatment(CIdentifier id)
 {
     Add(new OpCodeEmitter(OpCode.PUSHW, id.Name));
     Add(new OpCodeEmitter(OpCode.JMP));
 }