Index: doc/proposals/modules-alvin/1_stitched_modules/Driver.py
===================================================================
--- doc/proposals/modules-alvin/1_stitched_modules/Driver.py	(revision 3151bc098c7455c35a93a8f6de9f47dc4f0a07eb)
+++ doc/proposals/modules-alvin/1_stitched_modules/Driver.py	(revision 3151bc098c7455c35a93a8f6de9f47dc4f0a07eb)
@@ -0,0 +1,342 @@
+import argparse
+import os
+from pprint import pprint
+from antlr4 import *
+from parser.CMODLexer import CMODLexer
+from parser.CMODParser import CMODParser
+
+def parse_args():
+    parser = argparse.ArgumentParser()
+    parser.add_argument("input_file", help="file to parse")
+    parser.add_argument("-r", "--project_root", help="the root folder of the project, used to generate module names. All modules, including imports, should be within this folder")
+    args = parser.parse_args()
+    return args
+
+def main():
+    args = parse_args()
+    parse_top_level(args)
+
+def parse_top_level(args):
+    # args.input_file
+    # args.project_root
+
+    # This changes the OS directory to be project_root, and removes the suffix from input_file
+    # (it makes it easier to navigate the imports)
+    input_file = os.path.relpath(args.input_file, args.project_root)
+    os.chdir(args.project_root)
+    dot_index = input_file.rfind('.')
+    if dot_index < 0 or input_file[dot_index:] != '.cmod':
+        raise RuntimeError("input_file must use .cmod suffix")
+    input_file = input_file[:dot_index]
+
+    # Type notes to help you understand this code
+    # (it helps to have this open in another tab while reading the code)
+    #
+    # module_asts: dict[file_path: str, (text, tokens, tree)]
+    # module_imports: dict[file_path: str, list[imported_file_path: str]]
+    # text  # str
+    # tokens[0].text  # start, stop, line, column
+    # a, b = tree.getSourceInterval()  # getChildren, getChildCount, getChild
+    #
+    # module_data: dict[file_path: str, (types, variables)]
+    # types, variables: dict[name: str, 
+    #     (idx: int, used_names_decl, used_names_defn, is_exported: bool, AST)]
+    # used_names_decl, used_names_defn: 
+    #     list[(name: str, idx: int, is_variable: bool, needs_defn: bool)]
+    #
+    # module_input: dict[file_path: str, (type_symbol_table, var_symbol_table)]
+    # type_symbol_table, var_symbol_table: dict[name: str, file_path: str]
+
+    # This parses the input file, as well as any recursively imported modules
+    # (output: module_asts, module_imports)
+    module_asts = {}  # dict[file_path: str, (text, tokens, tree)]
+    module_imports = {}  # dict[file_path: str, list[imported_file_path: str]]
+    modules_to_process = [input_file]  # list[file_path: str]
+    while modules_to_process:
+        file_path = modules_to_process.pop()
+        if file_path in module_asts:
+            continue
+        if "." in file_path:
+            raise RuntimeError(f"{file_path=} contains '.', which is disallowed. Make sure {args.project_root=} contains all modules")
+        input_stream = FileStream(file_path + ".cmod")
+        text = str(input_stream)
+        lexer = CMODLexer(input_stream)
+        tokens = lexer.getAllTokens()  # list[token: {text, start, stop, line, column}]
+                                       # stop is inclusive, just like getSourceInterval
+        lexer.reset()
+        stream = CommonTokenStream(lexer)
+        parser = CMODParser(stream)
+        tree = parser.compilationUnit()  # {getSourceInterval, getChildren, getChildCount, getChild}
+        if parser.getNumberOfSyntaxErrors() > 0:
+            raise RuntimeError(f"syntax errors for file {file_path}")
+        module_asts[file_path] = text, tokens, tree
+
+        import_names = []  # list[import_name: str]
+        for importDeclaration in tree.getChild(0).getChildren():
+            if type(importDeclaration) != CMODParser.ImportDeclarationContext:
+                continue
+            numChildren = importDeclaration.getChildCount()
+            token_start, _ = importDeclaration.getChild(1).getSourceInterval()
+            text_start = tokens[token_start].start
+            _, token_end = importDeclaration.getChild(numChildren-2).getSourceInterval()
+            input_end = tokens[token_end].stop
+            import_name = text[text_start:input_end+1]
+            if import_name.startswith('"'):
+                import_name = import_name[1:len(import_name)-1]
+            import_names.append(import_name)
+        file_path_dir = os.path.split(file_path)[0]
+        import_file_paths = [os.path.normpath('./'+file_path_dir+'/'+x) for x in import_names]
+        module_imports[file_path] = import_file_paths
+        modules_to_process.extend(module_imports[file_path])
+
+    print("---- MODULE IMPORTS: ----")
+    pprint(module_imports)
+
+    # This analyzes each module, extracting top-level symbols
+    # (output: module_data)
+    module_data = {}  # dict[file_path: str, (types, variables)]
+    for file_path, (_, tokens, tree) in module_asts.items():
+        types, variables = {}, {}  # dict[name: str, (idx: int, used_names_decl, used_names_defn, is_exported: bool, AST)]
+        if tree.translationUnit() is None:
+            module_data[file_path] = types, variables
+            continue
+        for externalDeclaration in tree.translationUnit().externalDeclaration():
+            lfd = externalDeclaration.limitedFunctionDefinition()
+            lstruct = externalDeclaration.limitedStruct()
+            lg = externalDeclaration.limitedGlobal()
+            is_exported = tokens[externalDeclaration.getChild(0).getSourceInterval()[0]].text == 'export'
+            if lfd is not None:
+                used_names_decl, used_names_defn = [], []  # list[(name: str, idx: int, is_variable: bool, needs_defn: bool)]
+                return_struct = lfd.limitedTypeSpecifier().Identifier()
+                if return_struct is not None:
+                    idx, _ = return_struct.getSourceInterval()
+                    name = tokens[idx].text
+                    used_names_decl.append((name, idx, False, lfd.limitedDeclarator().getChildCount() == 1))
+                lpl = lfd.limitedParameterList()
+                if lpl is not None:
+                    lts_array = lpl.limitedTypeSpecifier()
+                    ld_array = lpl.limitedDeclarator()
+                    for lts, ld in zip(lts_array, ld_array):
+                        used_struct = lts.Identifier()
+                        if used_struct is not None:
+                            idx, _ = used_struct.getSourceInterval()
+                            name = tokens[idx].text
+                            used_names_decl.append((name, idx, False, ld.getChildCount() == 1))
+                for ls in lfd.limitedCompoundStatement().limitedStatement():
+                    idx, _ = ls.Identifier().getSourceInterval()
+                    name = tokens[idx].text
+                    used_names_defn.append((name, idx, ls.getChildCount() == 2, ls.getChildCount() == 3))
+
+                idx, _ = lfd.limitedDeclarator().Identifier().getSourceInterval()
+                name = tokens[idx].text
+
+                # Assume no overloading of names
+                variables[name] = idx, used_names_decl, used_names_defn, is_exported, lfd
+            elif lstruct is not None:
+                used_names_decl, used_names_defn = [], []
+                for ls in lstruct.limitedCompoundStatement().limitedStatement():
+                    idx, _ = ls.Identifier().getSourceInterval()
+                    name = tokens[idx].text
+                    used_names_defn.append((name, idx, ls.getChildCount() == 2, ls.getChildCount() == 3))
+
+                idx, _ = lstruct.Identifier().getSourceInterval()
+                name = tokens[idx].text
+
+                types[name] = idx, used_names_decl, used_names_defn, is_exported, lstruct
+            elif lg is not None:
+                used_names_decl, used_names_defn = [], []
+                struct_type = lg.limitedTypeSpecifier().Identifier()
+                if struct_type is not None:
+                    idx, _ = struct_type.getSourceInterval()
+                    name = tokens[idx].text
+                    # global decls actually don't need the struct defn
+                    used_names_decl.append((name, idx, False, False))
+                    used_names_defn.append((name, idx, False, lg.limitedDeclarator().getChildCount() == 1))
+                li = lg.limitedInitializer()
+                if li is not None:
+                    for identifier in li.Identifier():
+                        idx, _ = identifier.getSourceInterval()
+                        name = tokens[idx].text
+                        used_names_defn.append((name, idx, True, False))
+
+                idx, _ = lg.limitedDeclarator().Identifier().getSourceInterval()
+                name = tokens[idx].text
+
+                variables[name] = idx, used_names_decl, used_names_defn, is_exported, lg
+        module_data[file_path] = types, variables
+
+    print("---- MODULE DATA: ----")
+    pprint(module_data)
+
+    # This combines imported symbols to produce symbol tables for each module
+    # (output: module_input)
+    module_input = {}  # dict[file_path: str, (type_symbol_table, var_symbol_table)]
+    for file_path, imported_file_paths in module_imports.items():
+        type_symbol_table = {}  # dict[name: str, file_path: str]
+        var_symbol_table = {}  # dict[name: str, file_path: str]
+        for imported_file_path in imported_file_paths:
+            types, variables = module_data[imported_file_path]
+            # Assume no clashes (ie. overwrites)
+            for name, (_, _, _, is_exported, _) in types.items():
+                if is_exported:
+                    type_symbol_table[name] = imported_file_path
+            for name, (_, _, _, is_exported, _) in variables.items():
+                if is_exported:
+                    var_symbol_table[name] = imported_file_path
+        types, variables = module_data[file_path]
+        for name in types:
+            type_symbol_table[name] = file_path
+        for name in variables:
+            var_symbol_table[name] = file_path
+        module_input[file_path] = type_symbol_table, var_symbol_table
+
+    print("---- MODULE INPUT: ----")
+    pprint(module_input)
+
+    # This performs a topological ordering of any needed symbols, as well as renaming them to the correct module
+    # (output: module_output)
+    module_output = {}  # dict[file_path: str, generated_output: str]
+    for file_path in module_asts:
+        already_added = {}  # dict[(file_path: str, name: str, is_variable: bool), (idx: int, is_defn: bool)]
+        def is_already_added(file_path, name, is_variable: bool, trying_to_add_defn: bool):
+            if (file_path, name, is_variable) in already_added:
+                # This helps avoid double definitions
+                if trying_to_add_defn:
+                    _, is_defn = already_added[(file_path, name, is_variable)]
+                    return is_defn
+                else:
+                    return True
+            else:
+                return False
+
+        generated_parts = []  # list[symbol_output: str]
+        circular_check = set()  # set[file_path, name, is_variable, is_defn: bool]
+        def try_add_to_parts(file_path, name, is_variable, trying_to_add_defn, idx, used_names_decl, used_names_defn, ast):
+            if is_already_added(file_path, name, is_variable, trying_to_add_defn):
+                return
+            if (file_path, name, is_variable, trying_to_add_defn) in circular_check:
+                circular_reference_str = f"// Circular reference! {file_path}, {name}, {is_variable}, {trying_to_add_defn}"
+                print(circular_reference_str)
+                generated_parts.append(circular_reference_str)
+                return
+            circular_check.add((file_path, name, is_variable, trying_to_add_defn))
+
+            def add_necessary_symbols(used_names_):
+                for u_name, _, u_is_variable, needs_defn in used_names_:
+                    if u_name not in module_input[file_path][u_is_variable]:
+                        external_reference_str = f"// External reference! {file_path}, {u_name}, {u_is_variable}"
+                        print(external_reference_str)
+                        generated_parts.append(external_reference_str)
+                        continue
+                    m_file_path = module_input[file_path][u_is_variable][u_name]
+                    m_idx, m_used_names_decl, m_used_names_defn, _, m_ast = module_data[m_file_path][u_is_variable][u_name]
+                    try_add_to_parts(m_file_path, u_name, u_is_variable, needs_defn, m_idx, m_used_names_decl, m_used_names_defn, m_ast)
+            add_necessary_symbols(used_names_decl)
+            if trying_to_add_defn:
+                add_necessary_symbols(used_names_defn)
+            
+            text, tokens, _ = module_asts[file_path]
+            if trying_to_add_defn:
+                token_start, token_end = ast.getSourceInterval()
+                text_start = tokens[token_start].start
+                input_end = tokens[token_end].stop
+                symbol_output = text[text_start:input_end+1]
+            else:
+                token_start, _ = ast.getSourceInterval()
+                text_start = tokens[token_start].start
+                if type(ast) == CMODParser.LimitedFunctionDefinitionContext:
+                    token_end, _ = ast.limitedCompoundStatement().getSourceInterval()
+                    token_end -= 1
+                    while tokens[token_end].text.isspace():
+                        token_end -= 1
+                    input_end = tokens[token_end].stop
+                    symbol_output = text[text_start:input_end+1] + ';'
+                elif type(ast) == CMODParser.LimitedGlobalContext:
+                    _, token_end = ast.limitedDeclarator().getSourceInterval()
+                    input_end = tokens[token_end].stop
+                    extern_str = 'extern '
+                    symbol_output = extern_str + text[text_start:input_end+1] + ';'
+                    text_start -= len(extern_str)  # adjust text_start to make the rewriting work
+                elif type(ast) == CMODParser.LimitedStructContext:
+                    token_end, _ = ast.limitedCompoundStatement().getSourceInterval()
+                    token_end -= 1
+                    while tokens[token_end].text.isspace():
+                        token_end -= 1
+                    input_end = tokens[token_end].stop
+                    symbol_output = text[text_start:input_end+1] + ';'
+                else:
+                    assert False, "This code path should not be reached"
+            
+            # This renaming is very unoptimized and relies on used_names_* being in order
+            def full_name(file_path, name):
+                return file_path.replace('/', '$') + '$$' + name
+            def update_symbol_output(file_path, name, idx):
+                nonlocal symbol_output
+                replace_start = tokens[idx].start - text_start
+                replace_end = tokens[idx].stop - text_start
+                symbol_output = symbol_output[:replace_start] + full_name(file_path, name) + symbol_output[replace_end+1:]
+            if trying_to_add_defn:
+                for u_name, u_idx, u_is_variable, _ in reversed(used_names_defn):
+                    if u_name not in module_input[file_path][u_is_variable]:
+                        continue
+                    m_file_path = module_input[file_path][u_is_variable][u_name]
+                    update_symbol_output(m_file_path, u_name, u_idx)
+            for u_name, u_idx, u_is_variable, _ in reversed(used_names_decl):
+                if u_idx < idx:
+                    break
+                if u_name not in module_input[file_path][u_is_variable]:
+                    continue
+                m_file_path = module_input[file_path][u_is_variable][u_name]
+                update_symbol_output(m_file_path, u_name, u_idx)
+            update_symbol_output(file_path, name, idx)
+            for u_name, u_idx, u_is_variable, _ in reversed(used_names_decl):
+                if u_idx >= idx:
+                    continue
+                if u_name not in module_input[file_path][u_is_variable]:
+                    continue
+                m_file_path = module_input[file_path][u_is_variable][u_name]
+                update_symbol_output(m_file_path, u_name, u_idx)
+            generated_parts.append(symbol_output)
+
+            already_added[(file_path, name, is_variable)] = len(generated_parts)-1, trying_to_add_defn
+        
+        types, variables = module_data[file_path]
+        for name, (idx, used_names_decl, used_names_defn, _, ast) in types.items():
+            try_add_to_parts(file_path, name, False, True, idx, used_names_decl, used_names_defn, ast)
+        for name, (idx, used_names_decl, used_names_defn, _, ast) in variables.items():
+            try_add_to_parts(file_path, name, True, True, idx, used_names_decl, used_names_defn, ast)
+        module_output[file_path] = "\n\n".join(generated_parts)
+
+    for file_path, generated_output in module_output.items():
+        print(f"//////////////// START OF FILE {file_path} ////////////////")
+        print(generated_output)
+
+def simple_parse(input_file):
+    # Used in debugging
+    input_stream = FileStream(input_file)
+    lexer = CMODLexer(input_stream)
+    stream = CommonTokenStream(lexer)
+    parser = CMODParser(stream)
+    tree = parser.compilationUnit()
+    print(tree.getText())
+
+def details(ast):
+    # Used in debugging
+    print(f"Details for {repr(ast)}")
+    num_auto_expand = 0
+    while ast.getChildCount() == 1:
+        ast = ast.getChild(0)
+        num_auto_expand += 1
+        print(repr(ast))
+    if num_auto_expand:
+        print(f"auto expanded {num_auto_expand} times")
+    n = ast.getChildCount()
+    print(n)
+    for i in range(n):
+        print()
+        print(i)
+        print(repr(ast.getChild(i)))
+        print(ast.getChild(i).getText())
+
+if __name__ == '__main__':
+    main()
Index: doc/proposals/modules-alvin/1_stitched_modules/README.md
===================================================================
--- doc/proposals/modules-alvin/1_stitched_modules/README.md	(revision 3151bc098c7455c35a93a8f6de9f47dc4f0a07eb)
+++ doc/proposals/modules-alvin/1_stitched_modules/README.md	(revision 3151bc098c7455c35a93a8f6de9f47dc4f0a07eb)
@@ -0,0 +1,13 @@
+## Generating the parser code *(already done, in parser/)*
+
+Using ANTLR4 (v4.13.2) to parse grammars. See https://github.com/antlr/antlr4/blob/master/doc/getting-started.md for details. Run `pip install antlr4-tools` to get `antlr4` and `anltr4-parse` executables. Example command: `antlr4-parse parser/CMOD.g4 compilationUnit -gui testing/noImports.cmod`
+
+CMOD.g4 grammar inspired by https://github.com/antlr/grammars-v4/blob/master/c/C.g4 (though heavily edited afterwards). Ran `antlr4 -Dlanguage=Python3 parser/CMOD.g4` to generate parser code (you can add `-visitor -listener` flags for extra capabilities).
+
+## Running the code
+
+Adapted the steps from https://github.com/antlr/antlr4/blob/master/doc/python-target.md to generate output. Run `pip install -r requirements.txt` to get needed libraries, then `python3 Driver.py -r testing testing/noImports.cmod` to run on example code.
+
+## Documentation
+
+The concepts behind this prototype are discussed in `stitched_modules.md`
Index: doc/proposals/modules-alvin/1_stitched_modules/parser/CMOD.g4
===================================================================
--- doc/proposals/modules-alvin/1_stitched_modules/parser/CMOD.g4	(revision 3151bc098c7455c35a93a8f6de9f47dc4f0a07eb)
+++ doc/proposals/modules-alvin/1_stitched_modules/parser/CMOD.g4	(revision 3151bc098c7455c35a93a8f6de9f47dc4f0a07eb)
@@ -0,0 +1,107 @@
+// C-like language with expressions removed, used to showcase module capabilities
+
+grammar CMOD;
+
+compilationUnit
+    : translationUnit EOF
+    ;
+
+translationUnit
+    : moduleDeclaration importDeclaration* externalDeclaration*
+    ;
+
+moduleDeclaration
+    : 'module' ';'
+    ;
+
+importDeclaration
+    : 'import' (StringLiteral | (Identifier ('/' Identifier)*)) ';'
+    ;
+
+externalDeclaration
+    : 'export'? limitedFunctionDefinition
+    | 'export'? limitedGlobal
+    | 'export'? limitedStruct
+    | ';' // stray ;
+    ;
+
+limitedFunctionDefinition
+    : limitedTypeSpecifier limitedDeclarator '(' limitedParameterList?  ')' limitedCompoundStatement
+    ;
+
+limitedTypeSpecifier
+    : 'void'
+    | 'char'
+    | 'short'
+    | 'int'
+    | 'long'
+    | 'float'
+    | 'double'
+    | 'struct' Identifier
+    ;
+
+limitedDeclarator
+    : '*'? Identifier
+    ;
+
+limitedParameterList
+    : limitedTypeSpecifier limitedDeclarator (',' limitedTypeSpecifier limitedDeclarator)*
+    ;
+
+limitedCompoundStatement
+    : '{' limitedStatement* '}'
+    ;
+
+limitedStatement
+    : Identifier ';'  // these are values or functions
+    | 'type' Identifier ';'  // these are structs, need full definition
+    | 'type' '*' Identifier ';'  // these are structs, only need forward declaration
+    ;
+
+limitedGlobal
+    : limitedTypeSpecifier limitedDeclarator ('=' limitedInitializer)? ';'
+    ;
+
+limitedInitializer
+    : Identifier ('+' Identifier)* // these are values or functions
+    ;
+
+limitedStruct
+    : 'struct' Identifier limitedCompoundStatement ';'
+    ;
+
+Identifier
+    : Nondigit (Nondigit | Digit)*
+    ;
+
+fragment Nondigit
+    : [a-zA-Z_$]
+    ;
+
+fragment Digit
+    : [0-9]
+    ;
+
+StringLiteral
+    : '"' SChar* '"'
+    ;
+
+fragment SChar
+    : ~["\r\n]
+    ;
+
+Whitespace
+    : [ \t]+ -> channel(HIDDEN)
+    ;
+
+Newline
+    : ('\r' '\n'? | '\n') -> channel(HIDDEN)
+    ;
+
+BlockComment
+    : '/*' .*? '*/' -> channel(HIDDEN)
+    ;
+
+LineComment
+    : '//' ~[\r\n]* -> channel(HIDDEN)
+    ;
Index: doc/proposals/modules-alvin/1_stitched_modules/parser/CMOD.interp
===================================================================
--- doc/proposals/modules-alvin/1_stitched_modules/parser/CMOD.interp	(revision 3151bc098c7455c35a93a8f6de9f47dc4f0a07eb)
+++ doc/proposals/modules-alvin/1_stitched_modules/parser/CMOD.interp	(revision 3151bc098c7455c35a93a8f6de9f47dc4f0a07eb)
@@ -0,0 +1,81 @@
+token literal names:
+null
+'module'
+';'
+'import'
+'/'
+'export'
+'('
+')'
+'void'
+'char'
+'short'
+'int'
+'long'
+'float'
+'double'
+'struct'
+'*'
+','
+'{'
+'}'
+'type'
+'='
+'+'
+null
+null
+null
+null
+null
+null
+
+token symbolic names:
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+Identifier
+StringLiteral
+Whitespace
+Newline
+BlockComment
+LineComment
+
+rule names:
+compilationUnit
+translationUnit
+moduleDeclaration
+importDeclaration
+externalDeclaration
+limitedFunctionDefinition
+limitedTypeSpecifier
+limitedDeclarator
+limitedParameterList
+limitedCompoundStatement
+limitedStatement
+limitedGlobal
+limitedInitializer
+limitedStruct
+
+
+atn:
+[4, 1, 28, 154, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 5, 1, 34, 8, 1, 10, 1, 12, 1, 37, 9, 1, 1, 1, 5, 1, 40, 8, 1, 10, 1, 12, 1, 43, 9, 1, 1, 2, 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 5, 3, 53, 8, 3, 10, 3, 12, 3, 56, 9, 3, 3, 3, 58, 8, 3, 1, 3, 1, 3, 1, 4, 3, 4, 63, 8, 4, 1, 4, 1, 4, 3, 4, 67, 8, 4, 1, 4, 1, 4, 3, 4, 71, 8, 4, 1, 4, 1, 4, 3, 4, 75, 8, 4, 1, 5, 1, 5, 1, 5, 1, 5, 3, 5, 81, 8, 5, 1, 5, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 3, 6, 95, 8, 6, 1, 7, 3, 7, 98, 8, 7, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 5, 8, 108, 8, 8, 10, 8, 12, 8, 111, 9, 8, 1, 9, 1, 9, 5, 9, 115, 8, 9, 10, 9, 12, 9, 118, 9, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 3, 10, 131, 8, 10, 1, 11, 1, 11, 1, 11, 1, 11, 3, 11, 137, 8, 11, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 5, 12, 144, 8, 12, 10, 12, 12, 12, 147, 9, 12, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 0, 0, 14, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 0, 0, 164, 0, 28, 1, 0, 0, 0, 2, 31, 1, 0, 0, 0, 4, 44, 1, 0, 0, 0, 6, 47, 1, 0, 0, 0, 8, 74, 1, 0, 0, 0, 10, 76, 1, 0, 0, 0, 12, 94, 1, 0, 0, 0, 14, 97, 1, 0, 0, 0, 16, 101, 1, 0, 0, 0, 18, 112, 1, 0, 0, 0, 20, 130, 1, 0, 0, 0, 22, 132, 1, 0, 0, 0, 24, 140, 1, 0, 0, 0, 26, 148, 1, 0, 0, 0, 28, 29, 3, 2, 1, 0, 29, 30, 5, 0, 0, 1, 30, 1, 1, 0, 0, 0, 31, 35, 3, 4, 2, 0, 32, 34, 3, 6, 3, 0, 33, 32, 1, 0, 0, 0, 34, 37, 1, 0, 0, 0, 35, 33, 1, 0, 0, 0, 35, 36, 1, 0, 0, 0, 36, 41, 1, 0, 0, 0, 37, 35, 1, 0, 0, 0, 38, 40, 3, 8, 4, 0, 39, 38, 1, 0, 0, 0, 40, 43, 1, 0, 0, 0, 41, 39, 1, 0, 0, 0, 41, 42, 1, 0, 0, 0, 42, 3, 1, 0, 0, 0, 43, 41, 1, 0, 0, 0, 44, 45, 5, 1, 0, 0, 45, 46, 5, 2, 0, 0, 46, 5, 1, 0, 0, 0, 47, 57, 5, 3, 0, 0, 48, 58, 5, 24, 0, 0, 49, 54, 5, 23, 0, 0, 50, 51, 5, 4, 0, 0, 51, 53, 5, 23, 0, 0, 52, 50, 1, 0, 0, 0, 53, 56, 1, 0, 0, 0, 54, 52, 1, 0, 0, 0, 54, 55, 1, 0, 0, 0, 55, 58, 1, 0, 0, 0, 56, 54, 1, 0, 0, 0, 57, 48, 1, 0, 0, 0, 57, 49, 1, 0, 0, 0, 58, 59, 1, 0, 0, 0, 59, 60, 5, 2, 0, 0, 60, 7, 1, 0, 0, 0, 61, 63, 5, 5, 0, 0, 62, 61, 1, 0, 0, 0, 62, 63, 1, 0, 0, 0, 63, 64, 1, 0, 0, 0, 64, 75, 3, 10, 5, 0, 65, 67, 5, 5, 0, 0, 66, 65, 1, 0, 0, 0, 66, 67, 1, 0, 0, 0, 67, 68, 1, 0, 0, 0, 68, 75, 3, 22, 11, 0, 69, 71, 5, 5, 0, 0, 70, 69, 1, 0, 0, 0, 70, 71, 1, 0, 0, 0, 71, 72, 1, 0, 0, 0, 72, 75, 3, 26, 13, 0, 73, 75, 5, 2, 0, 0, 74, 62, 1, 0, 0, 0, 74, 66, 1, 0, 0, 0, 74, 70, 1, 0, 0, 0, 74, 73, 1, 0, 0, 0, 75, 9, 1, 0, 0, 0, 76, 77, 3, 12, 6, 0, 77, 78, 3, 14, 7, 0, 78, 80, 5, 6, 0, 0, 79, 81, 3, 16, 8, 0, 80, 79, 1, 0, 0, 0, 80, 81, 1, 0, 0, 0, 81, 82, 1, 0, 0, 0, 82, 83, 5, 7, 0, 0, 83, 84, 3, 18, 9, 0, 84, 11, 1, 0, 0, 0, 85, 95, 5, 8, 0, 0, 86, 95, 5, 9, 0, 0, 87, 95, 5, 10, 0, 0, 88, 95, 5, 11, 0, 0, 89, 95, 5, 12, 0, 0, 90, 95, 5, 13, 0, 0, 91, 95, 5, 14, 0, 0, 92, 93, 5, 15, 0, 0, 93, 95, 5, 23, 0, 0, 94, 85, 1, 0, 0, 0, 94, 86, 1, 0, 0, 0, 94, 87, 1, 0, 0, 0, 94, 88, 1, 0, 0, 0, 94, 89, 1, 0, 0, 0, 94, 90, 1, 0, 0, 0, 94, 91, 1, 0, 0, 0, 94, 92, 1, 0, 0, 0, 95, 13, 1, 0, 0, 0, 96, 98, 5, 16, 0, 0, 97, 96, 1, 0, 0, 0, 97, 98, 1, 0, 0, 0, 98, 99, 1, 0, 0, 0, 99, 100, 5, 23, 0, 0, 100, 15, 1, 0, 0, 0, 101, 102, 3, 12, 6, 0, 102, 109, 3, 14, 7, 0, 103, 104, 5, 17, 0, 0, 104, 105, 3, 12, 6, 0, 105, 106, 3, 14, 7, 0, 106, 108, 1, 0, 0, 0, 107, 103, 1, 0, 0, 0, 108, 111, 1, 0, 0, 0, 109, 107, 1, 0, 0, 0, 109, 110, 1, 0, 0, 0, 110, 17, 1, 0, 0, 0, 111, 109, 1, 0, 0, 0, 112, 116, 5, 18, 0, 0, 113, 115, 3, 20, 10, 0, 114, 113, 1, 0, 0, 0, 115, 118, 1, 0, 0, 0, 116, 114, 1, 0, 0, 0, 116, 117, 1, 0, 0, 0, 117, 119, 1, 0, 0, 0, 118, 116, 1, 0, 0, 0, 119, 120, 5, 19, 0, 0, 120, 19, 1, 0, 0, 0, 121, 122, 5, 23, 0, 0, 122, 131, 5, 2, 0, 0, 123, 124, 5, 20, 0, 0, 124, 125, 5, 23, 0, 0, 125, 131, 5, 2, 0, 0, 126, 127, 5, 20, 0, 0, 127, 128, 5, 16, 0, 0, 128, 129, 5, 23, 0, 0, 129, 131, 5, 2, 0, 0, 130, 121, 1, 0, 0, 0, 130, 123, 1, 0, 0, 0, 130, 126, 1, 0, 0, 0, 131, 21, 1, 0, 0, 0, 132, 133, 3, 12, 6, 0, 133, 136, 3, 14, 7, 0, 134, 135, 5, 21, 0, 0, 135, 137, 3, 24, 12, 0, 136, 134, 1, 0, 0, 0, 136, 137, 1, 0, 0, 0, 137, 138, 1, 0, 0, 0, 138, 139, 5, 2, 0, 0, 139, 23, 1, 0, 0, 0, 140, 145, 5, 23, 0, 0, 141, 142, 5, 22, 0, 0, 142, 144, 5, 23, 0, 0, 143, 141, 1, 0, 0, 0, 144, 147, 1, 0, 0, 0, 145, 143, 1, 0, 0, 0, 145, 146, 1, 0, 0, 0, 146, 25, 1, 0, 0, 0, 147, 145, 1, 0, 0, 0, 148, 149, 5, 15, 0, 0, 149, 150, 5, 23, 0, 0, 150, 151, 3, 18, 9, 0, 151, 152, 5, 2, 0, 0, 152, 27, 1, 0, 0, 0, 16, 35, 41, 54, 57, 62, 66, 70, 74, 80, 94, 97, 109, 116, 130, 136, 145]
Index: doc/proposals/modules-alvin/1_stitched_modules/parser/CMOD.tokens
===================================================================
--- doc/proposals/modules-alvin/1_stitched_modules/parser/CMOD.tokens	(revision 3151bc098c7455c35a93a8f6de9f47dc4f0a07eb)
+++ doc/proposals/modules-alvin/1_stitched_modules/parser/CMOD.tokens	(revision 3151bc098c7455c35a93a8f6de9f47dc4f0a07eb)
@@ -0,0 +1,50 @@
+T__0=1
+T__1=2
+T__2=3
+T__3=4
+T__4=5
+T__5=6
+T__6=7
+T__7=8
+T__8=9
+T__9=10
+T__10=11
+T__11=12
+T__12=13
+T__13=14
+T__14=15
+T__15=16
+T__16=17
+T__17=18
+T__18=19
+T__19=20
+T__20=21
+T__21=22
+Identifier=23
+StringLiteral=24
+Whitespace=25
+Newline=26
+BlockComment=27
+LineComment=28
+'module'=1
+';'=2
+'import'=3
+'/'=4
+'export'=5
+'('=6
+')'=7
+'void'=8
+'char'=9
+'short'=10
+'int'=11
+'long'=12
+'float'=13
+'double'=14
+'struct'=15
+'*'=16
+','=17
+'{'=18
+'}'=19
+'type'=20
+'='=21
+'+'=22
Index: doc/proposals/modules-alvin/1_stitched_modules/parser/CMODLexer.interp
===================================================================
--- doc/proposals/modules-alvin/1_stitched_modules/parser/CMODLexer.interp	(revision 3151bc098c7455c35a93a8f6de9f47dc4f0a07eb)
+++ doc/proposals/modules-alvin/1_stitched_modules/parser/CMODLexer.interp	(revision 3151bc098c7455c35a93a8f6de9f47dc4f0a07eb)
@@ -0,0 +1,104 @@
+token literal names:
+null
+'module'
+';'
+'import'
+'/'
+'export'
+'('
+')'
+'void'
+'char'
+'short'
+'int'
+'long'
+'float'
+'double'
+'struct'
+'*'
+','
+'{'
+'}'
+'type'
+'='
+'+'
+null
+null
+null
+null
+null
+null
+
+token symbolic names:
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+Identifier
+StringLiteral
+Whitespace
+Newline
+BlockComment
+LineComment
+
+rule names:
+T__0
+T__1
+T__2
+T__3
+T__4
+T__5
+T__6
+T__7
+T__8
+T__9
+T__10
+T__11
+T__12
+T__13
+T__14
+T__15
+T__16
+T__17
+T__18
+T__19
+T__20
+T__21
+Identifier
+Nondigit
+Digit
+StringLiteral
+SChar
+Whitespace
+Newline
+BlockComment
+LineComment
+
+channel names:
+DEFAULT_TOKEN_CHANNEL
+HIDDEN
+
+mode names:
+DEFAULT_MODE
+
+atn:
+[4, 0, 28, 218, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 3, 1, 3, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 6, 1, 6, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 10, 1, 10, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 15, 1, 15, 1, 16, 1, 16, 1, 17, 1, 17, 1, 18, 1, 18, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 20, 1, 20, 1, 21, 1, 21, 1, 22, 1, 22, 1, 22, 5, 22, 158, 8, 22, 10, 22, 12, 22, 161, 9, 22, 1, 23, 1, 23, 1, 24, 1, 24, 1, 25, 1, 25, 5, 25, 169, 8, 25, 10, 25, 12, 25, 172, 9, 25, 1, 25, 1, 25, 1, 26, 1, 26, 1, 27, 4, 27, 179, 8, 27, 11, 27, 12, 27, 180, 1, 27, 1, 27, 1, 28, 1, 28, 3, 28, 187, 8, 28, 1, 28, 3, 28, 190, 8, 28, 1, 28, 1, 28, 1, 29, 1, 29, 1, 29, 1, 29, 5, 29, 198, 8, 29, 10, 29, 12, 29, 201, 9, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 30, 1, 30, 1, 30, 1, 30, 5, 30, 212, 8, 30, 10, 30, 12, 30, 215, 9, 30, 1, 30, 1, 30, 1, 199, 0, 31, 1, 1, 3, 2, 5, 3, 7, 4, 9, 5, 11, 6, 13, 7, 15, 8, 17, 9, 19, 10, 21, 11, 23, 12, 25, 13, 27, 14, 29, 15, 31, 16, 33, 17, 35, 18, 37, 19, 39, 20, 41, 21, 43, 22, 45, 23, 47, 0, 49, 0, 51, 24, 53, 0, 55, 25, 57, 26, 59, 27, 61, 28, 1, 0, 5, 4, 0, 36, 36, 65, 90, 95, 95, 97, 122, 1, 0, 48, 57, 3, 0, 10, 10, 13, 13, 34, 34, 2, 0, 9, 9, 32, 32, 2, 0, 10, 10, 13, 13, 222, 0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 9, 1, 0, 0, 0, 0, 11, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, 0, 15, 1, 0, 0, 0, 0, 17, 1, 0, 0, 0, 0, 19, 1, 0, 0, 0, 0, 21, 1, 0, 0, 0, 0, 23, 1, 0, 0, 0, 0, 25, 1, 0, 0, 0, 0, 27, 1, 0, 0, 0, 0, 29, 1, 0, 0, 0, 0, 31, 1, 0, 0, 0, 0, 33, 1, 0, 0, 0, 0, 35, 1, 0, 0, 0, 0, 37, 1, 0, 0, 0, 0, 39, 1, 0, 0, 0, 0, 41, 1, 0, 0, 0, 0, 43, 1, 0, 0, 0, 0, 45, 1, 0, 0, 0, 0, 51, 1, 0, 0, 0, 0, 55, 1, 0, 0, 0, 0, 57, 1, 0, 0, 0, 0, 59, 1, 0, 0, 0, 0, 61, 1, 0, 0, 0, 1, 63, 1, 0, 0, 0, 3, 70, 1, 0, 0, 0, 5, 72, 1, 0, 0, 0, 7, 79, 1, 0, 0, 0, 9, 81, 1, 0, 0, 0, 11, 88, 1, 0, 0, 0, 13, 90, 1, 0, 0, 0, 15, 92, 1, 0, 0, 0, 17, 97, 1, 0, 0, 0, 19, 102, 1, 0, 0, 0, 21, 108, 1, 0, 0, 0, 23, 112, 1, 0, 0, 0, 25, 117, 1, 0, 0, 0, 27, 123, 1, 0, 0, 0, 29, 130, 1, 0, 0, 0, 31, 137, 1, 0, 0, 0, 33, 139, 1, 0, 0, 0, 35, 141, 1, 0, 0, 0, 37, 143, 1, 0, 0, 0, 39, 145, 1, 0, 0, 0, 41, 150, 1, 0, 0, 0, 43, 152, 1, 0, 0, 0, 45, 154, 1, 0, 0, 0, 47, 162, 1, 0, 0, 0, 49, 164, 1, 0, 0, 0, 51, 166, 1, 0, 0, 0, 53, 175, 1, 0, 0, 0, 55, 178, 1, 0, 0, 0, 57, 189, 1, 0, 0, 0, 59, 193, 1, 0, 0, 0, 61, 207, 1, 0, 0, 0, 63, 64, 5, 109, 0, 0, 64, 65, 5, 111, 0, 0, 65, 66, 5, 100, 0, 0, 66, 67, 5, 117, 0, 0, 67, 68, 5, 108, 0, 0, 68, 69, 5, 101, 0, 0, 69, 2, 1, 0, 0, 0, 70, 71, 5, 59, 0, 0, 71, 4, 1, 0, 0, 0, 72, 73, 5, 105, 0, 0, 73, 74, 5, 109, 0, 0, 74, 75, 5, 112, 0, 0, 75, 76, 5, 111, 0, 0, 76, 77, 5, 114, 0, 0, 77, 78, 5, 116, 0, 0, 78, 6, 1, 0, 0, 0, 79, 80, 5, 47, 0, 0, 80, 8, 1, 0, 0, 0, 81, 82, 5, 101, 0, 0, 82, 83, 5, 120, 0, 0, 83, 84, 5, 112, 0, 0, 84, 85, 5, 111, 0, 0, 85, 86, 5, 114, 0, 0, 86, 87, 5, 116, 0, 0, 87, 10, 1, 0, 0, 0, 88, 89, 5, 40, 0, 0, 89, 12, 1, 0, 0, 0, 90, 91, 5, 41, 0, 0, 91, 14, 1, 0, 0, 0, 92, 93, 5, 118, 0, 0, 93, 94, 5, 111, 0, 0, 94, 95, 5, 105, 0, 0, 95, 96, 5, 100, 0, 0, 96, 16, 1, 0, 0, 0, 97, 98, 5, 99, 0, 0, 98, 99, 5, 104, 0, 0, 99, 100, 5, 97, 0, 0, 100, 101, 5, 114, 0, 0, 101, 18, 1, 0, 0, 0, 102, 103, 5, 115, 0, 0, 103, 104, 5, 104, 0, 0, 104, 105, 5, 111, 0, 0, 105, 106, 5, 114, 0, 0, 106, 107, 5, 116, 0, 0, 107, 20, 1, 0, 0, 0, 108, 109, 5, 105, 0, 0, 109, 110, 5, 110, 0, 0, 110, 111, 5, 116, 0, 0, 111, 22, 1, 0, 0, 0, 112, 113, 5, 108, 0, 0, 113, 114, 5, 111, 0, 0, 114, 115, 5, 110, 0, 0, 115, 116, 5, 103, 0, 0, 116, 24, 1, 0, 0, 0, 117, 118, 5, 102, 0, 0, 118, 119, 5, 108, 0, 0, 119, 120, 5, 111, 0, 0, 120, 121, 5, 97, 0, 0, 121, 122, 5, 116, 0, 0, 122, 26, 1, 0, 0, 0, 123, 124, 5, 100, 0, 0, 124, 125, 5, 111, 0, 0, 125, 126, 5, 117, 0, 0, 126, 127, 5, 98, 0, 0, 127, 128, 5, 108, 0, 0, 128, 129, 5, 101, 0, 0, 129, 28, 1, 0, 0, 0, 130, 131, 5, 115, 0, 0, 131, 132, 5, 116, 0, 0, 132, 133, 5, 114, 0, 0, 133, 134, 5, 117, 0, 0, 134, 135, 5, 99, 0, 0, 135, 136, 5, 116, 0, 0, 136, 30, 1, 0, 0, 0, 137, 138, 5, 42, 0, 0, 138, 32, 1, 0, 0, 0, 139, 140, 5, 44, 0, 0, 140, 34, 1, 0, 0, 0, 141, 142, 5, 123, 0, 0, 142, 36, 1, 0, 0, 0, 143, 144, 5, 125, 0, 0, 144, 38, 1, 0, 0, 0, 145, 146, 5, 116, 0, 0, 146, 147, 5, 121, 0, 0, 147, 148, 5, 112, 0, 0, 148, 149, 5, 101, 0, 0, 149, 40, 1, 0, 0, 0, 150, 151, 5, 61, 0, 0, 151, 42, 1, 0, 0, 0, 152, 153, 5, 43, 0, 0, 153, 44, 1, 0, 0, 0, 154, 159, 3, 47, 23, 0, 155, 158, 3, 47, 23, 0, 156, 158, 3, 49, 24, 0, 157, 155, 1, 0, 0, 0, 157, 156, 1, 0, 0, 0, 158, 161, 1, 0, 0, 0, 159, 157, 1, 0, 0, 0, 159, 160, 1, 0, 0, 0, 160, 46, 1, 0, 0, 0, 161, 159, 1, 0, 0, 0, 162, 163, 7, 0, 0, 0, 163, 48, 1, 0, 0, 0, 164, 165, 7, 1, 0, 0, 165, 50, 1, 0, 0, 0, 166, 170, 5, 34, 0, 0, 167, 169, 3, 53, 26, 0, 168, 167, 1, 0, 0, 0, 169, 172, 1, 0, 0, 0, 170, 168, 1, 0, 0, 0, 170, 171, 1, 0, 0, 0, 171, 173, 1, 0, 0, 0, 172, 170, 1, 0, 0, 0, 173, 174, 5, 34, 0, 0, 174, 52, 1, 0, 0, 0, 175, 176, 8, 2, 0, 0, 176, 54, 1, 0, 0, 0, 177, 179, 7, 3, 0, 0, 178, 177, 1, 0, 0, 0, 179, 180, 1, 0, 0, 0, 180, 178, 1, 0, 0, 0, 180, 181, 1, 0, 0, 0, 181, 182, 1, 0, 0, 0, 182, 183, 6, 27, 0, 0, 183, 56, 1, 0, 0, 0, 184, 186, 5, 13, 0, 0, 185, 187, 5, 10, 0, 0, 186, 185, 1, 0, 0, 0, 186, 187, 1, 0, 0, 0, 187, 190, 1, 0, 0, 0, 188, 190, 5, 10, 0, 0, 189, 184, 1, 0, 0, 0, 189, 188, 1, 0, 0, 0, 190, 191, 1, 0, 0, 0, 191, 192, 6, 28, 0, 0, 192, 58, 1, 0, 0, 0, 193, 194, 5, 47, 0, 0, 194, 195, 5, 42, 0, 0, 195, 199, 1, 0, 0, 0, 196, 198, 9, 0, 0, 0, 197, 196, 1, 0, 0, 0, 198, 201, 1, 0, 0, 0, 199, 200, 1, 0, 0, 0, 199, 197, 1, 0, 0, 0, 200, 202, 1, 0, 0, 0, 201, 199, 1, 0, 0, 0, 202, 203, 5, 42, 0, 0, 203, 204, 5, 47, 0, 0, 204, 205, 1, 0, 0, 0, 205, 206, 6, 29, 0, 0, 206, 60, 1, 0, 0, 0, 207, 208, 5, 47, 0, 0, 208, 209, 5, 47, 0, 0, 209, 213, 1, 0, 0, 0, 210, 212, 8, 4, 0, 0, 211, 210, 1, 0, 0, 0, 212, 215, 1, 0, 0, 0, 213, 211, 1, 0, 0, 0, 213, 214, 1, 0, 0, 0, 214, 216, 1, 0, 0, 0, 215, 213, 1, 0, 0, 0, 216, 217, 6, 30, 0, 0, 217, 62, 1, 0, 0, 0, 9, 0, 157, 159, 170, 180, 186, 189, 199, 213, 1, 0, 1, 0]
Index: doc/proposals/modules-alvin/1_stitched_modules/parser/CMODLexer.py
===================================================================
--- doc/proposals/modules-alvin/1_stitched_modules/parser/CMODLexer.py	(revision 3151bc098c7455c35a93a8f6de9f47dc4f0a07eb)
+++ doc/proposals/modules-alvin/1_stitched_modules/parser/CMODLexer.py	(revision 3151bc098c7455c35a93a8f6de9f47dc4f0a07eb)
@@ -0,0 +1,155 @@
+# Generated from parser/CMOD.g4 by ANTLR 4.13.2
+from antlr4 import *
+from io import StringIO
+import sys
+if sys.version_info[1] > 5:
+    from typing import TextIO
+else:
+    from typing.io import TextIO
+
+
+def serializedATN():
+    return [
+        4,0,28,218,6,-1,2,0,7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5,
+        2,6,7,6,2,7,7,7,2,8,7,8,2,9,7,9,2,10,7,10,2,11,7,11,2,12,7,12,2,
+        13,7,13,2,14,7,14,2,15,7,15,2,16,7,16,2,17,7,17,2,18,7,18,2,19,7,
+        19,2,20,7,20,2,21,7,21,2,22,7,22,2,23,7,23,2,24,7,24,2,25,7,25,2,
+        26,7,26,2,27,7,27,2,28,7,28,2,29,7,29,2,30,7,30,1,0,1,0,1,0,1,0,
+        1,0,1,0,1,0,1,1,1,1,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,3,1,3,1,4,1,4,
+        1,4,1,4,1,4,1,4,1,4,1,5,1,5,1,6,1,6,1,7,1,7,1,7,1,7,1,7,1,8,1,8,
+        1,8,1,8,1,8,1,9,1,9,1,9,1,9,1,9,1,9,1,10,1,10,1,10,1,10,1,11,1,11,
+        1,11,1,11,1,11,1,12,1,12,1,12,1,12,1,12,1,12,1,13,1,13,1,13,1,13,
+        1,13,1,13,1,13,1,14,1,14,1,14,1,14,1,14,1,14,1,14,1,15,1,15,1,16,
+        1,16,1,17,1,17,1,18,1,18,1,19,1,19,1,19,1,19,1,19,1,20,1,20,1,21,
+        1,21,1,22,1,22,1,22,5,22,158,8,22,10,22,12,22,161,9,22,1,23,1,23,
+        1,24,1,24,1,25,1,25,5,25,169,8,25,10,25,12,25,172,9,25,1,25,1,25,
+        1,26,1,26,1,27,4,27,179,8,27,11,27,12,27,180,1,27,1,27,1,28,1,28,
+        3,28,187,8,28,1,28,3,28,190,8,28,1,28,1,28,1,29,1,29,1,29,1,29,5,
+        29,198,8,29,10,29,12,29,201,9,29,1,29,1,29,1,29,1,29,1,29,1,30,1,
+        30,1,30,1,30,5,30,212,8,30,10,30,12,30,215,9,30,1,30,1,30,1,199,
+        0,31,1,1,3,2,5,3,7,4,9,5,11,6,13,7,15,8,17,9,19,10,21,11,23,12,25,
+        13,27,14,29,15,31,16,33,17,35,18,37,19,39,20,41,21,43,22,45,23,47,
+        0,49,0,51,24,53,0,55,25,57,26,59,27,61,28,1,0,5,4,0,36,36,65,90,
+        95,95,97,122,1,0,48,57,3,0,10,10,13,13,34,34,2,0,9,9,32,32,2,0,10,
+        10,13,13,222,0,1,1,0,0,0,0,3,1,0,0,0,0,5,1,0,0,0,0,7,1,0,0,0,0,9,
+        1,0,0,0,0,11,1,0,0,0,0,13,1,0,0,0,0,15,1,0,0,0,0,17,1,0,0,0,0,19,
+        1,0,0,0,0,21,1,0,0,0,0,23,1,0,0,0,0,25,1,0,0,0,0,27,1,0,0,0,0,29,
+        1,0,0,0,0,31,1,0,0,0,0,33,1,0,0,0,0,35,1,0,0,0,0,37,1,0,0,0,0,39,
+        1,0,0,0,0,41,1,0,0,0,0,43,1,0,0,0,0,45,1,0,0,0,0,51,1,0,0,0,0,55,
+        1,0,0,0,0,57,1,0,0,0,0,59,1,0,0,0,0,61,1,0,0,0,1,63,1,0,0,0,3,70,
+        1,0,0,0,5,72,1,0,0,0,7,79,1,0,0,0,9,81,1,0,0,0,11,88,1,0,0,0,13,
+        90,1,0,0,0,15,92,1,0,0,0,17,97,1,0,0,0,19,102,1,0,0,0,21,108,1,0,
+        0,0,23,112,1,0,0,0,25,117,1,0,0,0,27,123,1,0,0,0,29,130,1,0,0,0,
+        31,137,1,0,0,0,33,139,1,0,0,0,35,141,1,0,0,0,37,143,1,0,0,0,39,145,
+        1,0,0,0,41,150,1,0,0,0,43,152,1,0,0,0,45,154,1,0,0,0,47,162,1,0,
+        0,0,49,164,1,0,0,0,51,166,1,0,0,0,53,175,1,0,0,0,55,178,1,0,0,0,
+        57,189,1,0,0,0,59,193,1,0,0,0,61,207,1,0,0,0,63,64,5,109,0,0,64,
+        65,5,111,0,0,65,66,5,100,0,0,66,67,5,117,0,0,67,68,5,108,0,0,68,
+        69,5,101,0,0,69,2,1,0,0,0,70,71,5,59,0,0,71,4,1,0,0,0,72,73,5,105,
+        0,0,73,74,5,109,0,0,74,75,5,112,0,0,75,76,5,111,0,0,76,77,5,114,
+        0,0,77,78,5,116,0,0,78,6,1,0,0,0,79,80,5,47,0,0,80,8,1,0,0,0,81,
+        82,5,101,0,0,82,83,5,120,0,0,83,84,5,112,0,0,84,85,5,111,0,0,85,
+        86,5,114,0,0,86,87,5,116,0,0,87,10,1,0,0,0,88,89,5,40,0,0,89,12,
+        1,0,0,0,90,91,5,41,0,0,91,14,1,0,0,0,92,93,5,118,0,0,93,94,5,111,
+        0,0,94,95,5,105,0,0,95,96,5,100,0,0,96,16,1,0,0,0,97,98,5,99,0,0,
+        98,99,5,104,0,0,99,100,5,97,0,0,100,101,5,114,0,0,101,18,1,0,0,0,
+        102,103,5,115,0,0,103,104,5,104,0,0,104,105,5,111,0,0,105,106,5,
+        114,0,0,106,107,5,116,0,0,107,20,1,0,0,0,108,109,5,105,0,0,109,110,
+        5,110,0,0,110,111,5,116,0,0,111,22,1,0,0,0,112,113,5,108,0,0,113,
+        114,5,111,0,0,114,115,5,110,0,0,115,116,5,103,0,0,116,24,1,0,0,0,
+        117,118,5,102,0,0,118,119,5,108,0,0,119,120,5,111,0,0,120,121,5,
+        97,0,0,121,122,5,116,0,0,122,26,1,0,0,0,123,124,5,100,0,0,124,125,
+        5,111,0,0,125,126,5,117,0,0,126,127,5,98,0,0,127,128,5,108,0,0,128,
+        129,5,101,0,0,129,28,1,0,0,0,130,131,5,115,0,0,131,132,5,116,0,0,
+        132,133,5,114,0,0,133,134,5,117,0,0,134,135,5,99,0,0,135,136,5,116,
+        0,0,136,30,1,0,0,0,137,138,5,42,0,0,138,32,1,0,0,0,139,140,5,44,
+        0,0,140,34,1,0,0,0,141,142,5,123,0,0,142,36,1,0,0,0,143,144,5,125,
+        0,0,144,38,1,0,0,0,145,146,5,116,0,0,146,147,5,121,0,0,147,148,5,
+        112,0,0,148,149,5,101,0,0,149,40,1,0,0,0,150,151,5,61,0,0,151,42,
+        1,0,0,0,152,153,5,43,0,0,153,44,1,0,0,0,154,159,3,47,23,0,155,158,
+        3,47,23,0,156,158,3,49,24,0,157,155,1,0,0,0,157,156,1,0,0,0,158,
+        161,1,0,0,0,159,157,1,0,0,0,159,160,1,0,0,0,160,46,1,0,0,0,161,159,
+        1,0,0,0,162,163,7,0,0,0,163,48,1,0,0,0,164,165,7,1,0,0,165,50,1,
+        0,0,0,166,170,5,34,0,0,167,169,3,53,26,0,168,167,1,0,0,0,169,172,
+        1,0,0,0,170,168,1,0,0,0,170,171,1,0,0,0,171,173,1,0,0,0,172,170,
+        1,0,0,0,173,174,5,34,0,0,174,52,1,0,0,0,175,176,8,2,0,0,176,54,1,
+        0,0,0,177,179,7,3,0,0,178,177,1,0,0,0,179,180,1,0,0,0,180,178,1,
+        0,0,0,180,181,1,0,0,0,181,182,1,0,0,0,182,183,6,27,0,0,183,56,1,
+        0,0,0,184,186,5,13,0,0,185,187,5,10,0,0,186,185,1,0,0,0,186,187,
+        1,0,0,0,187,190,1,0,0,0,188,190,5,10,0,0,189,184,1,0,0,0,189,188,
+        1,0,0,0,190,191,1,0,0,0,191,192,6,28,0,0,192,58,1,0,0,0,193,194,
+        5,47,0,0,194,195,5,42,0,0,195,199,1,0,0,0,196,198,9,0,0,0,197,196,
+        1,0,0,0,198,201,1,0,0,0,199,200,1,0,0,0,199,197,1,0,0,0,200,202,
+        1,0,0,0,201,199,1,0,0,0,202,203,5,42,0,0,203,204,5,47,0,0,204,205,
+        1,0,0,0,205,206,6,29,0,0,206,60,1,0,0,0,207,208,5,47,0,0,208,209,
+        5,47,0,0,209,213,1,0,0,0,210,212,8,4,0,0,211,210,1,0,0,0,212,215,
+        1,0,0,0,213,211,1,0,0,0,213,214,1,0,0,0,214,216,1,0,0,0,215,213,
+        1,0,0,0,216,217,6,30,0,0,217,62,1,0,0,0,9,0,157,159,170,180,186,
+        189,199,213,1,0,1,0
+    ]
+
+class CMODLexer(Lexer):
+
+    atn = ATNDeserializer().deserialize(serializedATN())
+
+    decisionsToDFA = [ DFA(ds, i) for i, ds in enumerate(atn.decisionToState) ]
+
+    T__0 = 1
+    T__1 = 2
+    T__2 = 3
+    T__3 = 4
+    T__4 = 5
+    T__5 = 6
+    T__6 = 7
+    T__7 = 8
+    T__8 = 9
+    T__9 = 10
+    T__10 = 11
+    T__11 = 12
+    T__12 = 13
+    T__13 = 14
+    T__14 = 15
+    T__15 = 16
+    T__16 = 17
+    T__17 = 18
+    T__18 = 19
+    T__19 = 20
+    T__20 = 21
+    T__21 = 22
+    Identifier = 23
+    StringLiteral = 24
+    Whitespace = 25
+    Newline = 26
+    BlockComment = 27
+    LineComment = 28
+
+    channelNames = [ u"DEFAULT_TOKEN_CHANNEL", u"HIDDEN" ]
+
+    modeNames = [ "DEFAULT_MODE" ]
+
+    literalNames = [ "<INVALID>",
+            "'module'", "';'", "'import'", "'/'", "'export'", "'('", "')'", 
+            "'void'", "'char'", "'short'", "'int'", "'long'", "'float'", 
+            "'double'", "'struct'", "'*'", "','", "'{'", "'}'", "'type'", 
+            "'='", "'+'" ]
+
+    symbolicNames = [ "<INVALID>",
+            "Identifier", "StringLiteral", "Whitespace", "Newline", "BlockComment", 
+            "LineComment" ]
+
+    ruleNames = [ "T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", 
+                  "T__7", "T__8", "T__9", "T__10", "T__11", "T__12", "T__13", 
+                  "T__14", "T__15", "T__16", "T__17", "T__18", "T__19", 
+                  "T__20", "T__21", "Identifier", "Nondigit", "Digit", "StringLiteral", 
+                  "SChar", "Whitespace", "Newline", "BlockComment", "LineComment" ]
+
+    grammarFileName = "CMOD.g4"
+
+    def __init__(self, input=None, output:TextIO = sys.stdout):
+        super().__init__(input, output)
+        self.checkVersion("4.13.2")
+        self._interp = LexerATNSimulator(self, self.atn, self.decisionsToDFA, PredictionContextCache())
+        self._actions = None
+        self._predicates = None
+
+
Index: doc/proposals/modules-alvin/1_stitched_modules/parser/CMODLexer.tokens
===================================================================
--- doc/proposals/modules-alvin/1_stitched_modules/parser/CMODLexer.tokens	(revision 3151bc098c7455c35a93a8f6de9f47dc4f0a07eb)
+++ doc/proposals/modules-alvin/1_stitched_modules/parser/CMODLexer.tokens	(revision 3151bc098c7455c35a93a8f6de9f47dc4f0a07eb)
@@ -0,0 +1,50 @@
+T__0=1
+T__1=2
+T__2=3
+T__3=4
+T__4=5
+T__5=6
+T__6=7
+T__7=8
+T__8=9
+T__9=10
+T__10=11
+T__11=12
+T__12=13
+T__13=14
+T__14=15
+T__15=16
+T__16=17
+T__17=18
+T__18=19
+T__19=20
+T__20=21
+T__21=22
+Identifier=23
+StringLiteral=24
+Whitespace=25
+Newline=26
+BlockComment=27
+LineComment=28
+'module'=1
+';'=2
+'import'=3
+'/'=4
+'export'=5
+'('=6
+')'=7
+'void'=8
+'char'=9
+'short'=10
+'int'=11
+'long'=12
+'float'=13
+'double'=14
+'struct'=15
+'*'=16
+','=17
+'{'=18
+'}'=19
+'type'=20
+'='=21
+'+'=22
Index: doc/proposals/modules-alvin/1_stitched_modules/parser/CMODListener.py
===================================================================
--- doc/proposals/modules-alvin/1_stitched_modules/parser/CMODListener.py	(revision 3151bc098c7455c35a93a8f6de9f47dc4f0a07eb)
+++ doc/proposals/modules-alvin/1_stitched_modules/parser/CMODListener.py	(revision 3151bc098c7455c35a93a8f6de9f47dc4f0a07eb)
@@ -0,0 +1,138 @@
+# Generated from parser/CMOD.g4 by ANTLR 4.13.2
+from antlr4 import *
+if "." in __name__:
+    from .CMODParser import CMODParser
+else:
+    from CMODParser import CMODParser
+
+# This class defines a complete listener for a parse tree produced by CMODParser.
+class CMODListener(ParseTreeListener):
+
+    # Enter a parse tree produced by CMODParser#compilationUnit.
+    def enterCompilationUnit(self, ctx:CMODParser.CompilationUnitContext):
+        pass
+
+    # Exit a parse tree produced by CMODParser#compilationUnit.
+    def exitCompilationUnit(self, ctx:CMODParser.CompilationUnitContext):
+        pass
+
+
+    # Enter a parse tree produced by CMODParser#translationUnit.
+    def enterTranslationUnit(self, ctx:CMODParser.TranslationUnitContext):
+        pass
+
+    # Exit a parse tree produced by CMODParser#translationUnit.
+    def exitTranslationUnit(self, ctx:CMODParser.TranslationUnitContext):
+        pass
+
+
+    # Enter a parse tree produced by CMODParser#moduleDeclaration.
+    def enterModuleDeclaration(self, ctx:CMODParser.ModuleDeclarationContext):
+        pass
+
+    # Exit a parse tree produced by CMODParser#moduleDeclaration.
+    def exitModuleDeclaration(self, ctx:CMODParser.ModuleDeclarationContext):
+        pass
+
+
+    # Enter a parse tree produced by CMODParser#importDeclaration.
+    def enterImportDeclaration(self, ctx:CMODParser.ImportDeclarationContext):
+        pass
+
+    # Exit a parse tree produced by CMODParser#importDeclaration.
+    def exitImportDeclaration(self, ctx:CMODParser.ImportDeclarationContext):
+        pass
+
+
+    # Enter a parse tree produced by CMODParser#externalDeclaration.
+    def enterExternalDeclaration(self, ctx:CMODParser.ExternalDeclarationContext):
+        pass
+
+    # Exit a parse tree produced by CMODParser#externalDeclaration.
+    def exitExternalDeclaration(self, ctx:CMODParser.ExternalDeclarationContext):
+        pass
+
+
+    # Enter a parse tree produced by CMODParser#limitedFunctionDefinition.
+    def enterLimitedFunctionDefinition(self, ctx:CMODParser.LimitedFunctionDefinitionContext):
+        pass
+
+    # Exit a parse tree produced by CMODParser#limitedFunctionDefinition.
+    def exitLimitedFunctionDefinition(self, ctx:CMODParser.LimitedFunctionDefinitionContext):
+        pass
+
+
+    # Enter a parse tree produced by CMODParser#limitedTypeSpecifier.
+    def enterLimitedTypeSpecifier(self, ctx:CMODParser.LimitedTypeSpecifierContext):
+        pass
+
+    # Exit a parse tree produced by CMODParser#limitedTypeSpecifier.
+    def exitLimitedTypeSpecifier(self, ctx:CMODParser.LimitedTypeSpecifierContext):
+        pass
+
+
+    # Enter a parse tree produced by CMODParser#limitedDeclarator.
+    def enterLimitedDeclarator(self, ctx:CMODParser.LimitedDeclaratorContext):
+        pass
+
+    # Exit a parse tree produced by CMODParser#limitedDeclarator.
+    def exitLimitedDeclarator(self, ctx:CMODParser.LimitedDeclaratorContext):
+        pass
+
+
+    # Enter a parse tree produced by CMODParser#limitedParameterList.
+    def enterLimitedParameterList(self, ctx:CMODParser.LimitedParameterListContext):
+        pass
+
+    # Exit a parse tree produced by CMODParser#limitedParameterList.
+    def exitLimitedParameterList(self, ctx:CMODParser.LimitedParameterListContext):
+        pass
+
+
+    # Enter a parse tree produced by CMODParser#limitedCompoundStatement.
+    def enterLimitedCompoundStatement(self, ctx:CMODParser.LimitedCompoundStatementContext):
+        pass
+
+    # Exit a parse tree produced by CMODParser#limitedCompoundStatement.
+    def exitLimitedCompoundStatement(self, ctx:CMODParser.LimitedCompoundStatementContext):
+        pass
+
+
+    # Enter a parse tree produced by CMODParser#limitedStatement.
+    def enterLimitedStatement(self, ctx:CMODParser.LimitedStatementContext):
+        pass
+
+    # Exit a parse tree produced by CMODParser#limitedStatement.
+    def exitLimitedStatement(self, ctx:CMODParser.LimitedStatementContext):
+        pass
+
+
+    # Enter a parse tree produced by CMODParser#limitedGlobal.
+    def enterLimitedGlobal(self, ctx:CMODParser.LimitedGlobalContext):
+        pass
+
+    # Exit a parse tree produced by CMODParser#limitedGlobal.
+    def exitLimitedGlobal(self, ctx:CMODParser.LimitedGlobalContext):
+        pass
+
+
+    # Enter a parse tree produced by CMODParser#limitedInitializer.
+    def enterLimitedInitializer(self, ctx:CMODParser.LimitedInitializerContext):
+        pass
+
+    # Exit a parse tree produced by CMODParser#limitedInitializer.
+    def exitLimitedInitializer(self, ctx:CMODParser.LimitedInitializerContext):
+        pass
+
+
+    # Enter a parse tree produced by CMODParser#limitedStruct.
+    def enterLimitedStruct(self, ctx:CMODParser.LimitedStructContext):
+        pass
+
+    # Exit a parse tree produced by CMODParser#limitedStruct.
+    def exitLimitedStruct(self, ctx:CMODParser.LimitedStructContext):
+        pass
+
+
+
+del CMODParser
Index: doc/proposals/modules-alvin/1_stitched_modules/parser/CMODParser.py
===================================================================
--- doc/proposals/modules-alvin/1_stitched_modules/parser/CMODParser.py	(revision 3151bc098c7455c35a93a8f6de9f47dc4f0a07eb)
+++ doc/proposals/modules-alvin/1_stitched_modules/parser/CMODParser.py	(revision 3151bc098c7455c35a93a8f6de9f47dc4f0a07eb)
@@ -0,0 +1,1072 @@
+# Generated from parser/CMOD.g4 by ANTLR 4.13.2
+# encoding: utf-8
+from antlr4 import *
+from io import StringIO
+import sys
+if sys.version_info[1] > 5:
+	from typing import TextIO
+else:
+	from typing.io import TextIO
+
+def serializedATN():
+    return [
+        4,1,28,154,2,0,7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5,2,6,7,
+        6,2,7,7,7,2,8,7,8,2,9,7,9,2,10,7,10,2,11,7,11,2,12,7,12,2,13,7,13,
+        1,0,1,0,1,0,1,1,1,1,5,1,34,8,1,10,1,12,1,37,9,1,1,1,5,1,40,8,1,10,
+        1,12,1,43,9,1,1,2,1,2,1,2,1,3,1,3,1,3,1,3,1,3,5,3,53,8,3,10,3,12,
+        3,56,9,3,3,3,58,8,3,1,3,1,3,1,4,3,4,63,8,4,1,4,1,4,3,4,67,8,4,1,
+        4,1,4,3,4,71,8,4,1,4,1,4,3,4,75,8,4,1,5,1,5,1,5,1,5,3,5,81,8,5,1,
+        5,1,5,1,5,1,6,1,6,1,6,1,6,1,6,1,6,1,6,1,6,1,6,3,6,95,8,6,1,7,3,7,
+        98,8,7,1,7,1,7,1,8,1,8,1,8,1,8,1,8,1,8,5,8,108,8,8,10,8,12,8,111,
+        9,8,1,9,1,9,5,9,115,8,9,10,9,12,9,118,9,9,1,9,1,9,1,10,1,10,1,10,
+        1,10,1,10,1,10,1,10,1,10,1,10,3,10,131,8,10,1,11,1,11,1,11,1,11,
+        3,11,137,8,11,1,11,1,11,1,12,1,12,1,12,5,12,144,8,12,10,12,12,12,
+        147,9,12,1,13,1,13,1,13,1,13,1,13,1,13,0,0,14,0,2,4,6,8,10,12,14,
+        16,18,20,22,24,26,0,0,164,0,28,1,0,0,0,2,31,1,0,0,0,4,44,1,0,0,0,
+        6,47,1,0,0,0,8,74,1,0,0,0,10,76,1,0,0,0,12,94,1,0,0,0,14,97,1,0,
+        0,0,16,101,1,0,0,0,18,112,1,0,0,0,20,130,1,0,0,0,22,132,1,0,0,0,
+        24,140,1,0,0,0,26,148,1,0,0,0,28,29,3,2,1,0,29,30,5,0,0,1,30,1,1,
+        0,0,0,31,35,3,4,2,0,32,34,3,6,3,0,33,32,1,0,0,0,34,37,1,0,0,0,35,
+        33,1,0,0,0,35,36,1,0,0,0,36,41,1,0,0,0,37,35,1,0,0,0,38,40,3,8,4,
+        0,39,38,1,0,0,0,40,43,1,0,0,0,41,39,1,0,0,0,41,42,1,0,0,0,42,3,1,
+        0,0,0,43,41,1,0,0,0,44,45,5,1,0,0,45,46,5,2,0,0,46,5,1,0,0,0,47,
+        57,5,3,0,0,48,58,5,24,0,0,49,54,5,23,0,0,50,51,5,4,0,0,51,53,5,23,
+        0,0,52,50,1,0,0,0,53,56,1,0,0,0,54,52,1,0,0,0,54,55,1,0,0,0,55,58,
+        1,0,0,0,56,54,1,0,0,0,57,48,1,0,0,0,57,49,1,0,0,0,58,59,1,0,0,0,
+        59,60,5,2,0,0,60,7,1,0,0,0,61,63,5,5,0,0,62,61,1,0,0,0,62,63,1,0,
+        0,0,63,64,1,0,0,0,64,75,3,10,5,0,65,67,5,5,0,0,66,65,1,0,0,0,66,
+        67,1,0,0,0,67,68,1,0,0,0,68,75,3,22,11,0,69,71,5,5,0,0,70,69,1,0,
+        0,0,70,71,1,0,0,0,71,72,1,0,0,0,72,75,3,26,13,0,73,75,5,2,0,0,74,
+        62,1,0,0,0,74,66,1,0,0,0,74,70,1,0,0,0,74,73,1,0,0,0,75,9,1,0,0,
+        0,76,77,3,12,6,0,77,78,3,14,7,0,78,80,5,6,0,0,79,81,3,16,8,0,80,
+        79,1,0,0,0,80,81,1,0,0,0,81,82,1,0,0,0,82,83,5,7,0,0,83,84,3,18,
+        9,0,84,11,1,0,0,0,85,95,5,8,0,0,86,95,5,9,0,0,87,95,5,10,0,0,88,
+        95,5,11,0,0,89,95,5,12,0,0,90,95,5,13,0,0,91,95,5,14,0,0,92,93,5,
+        15,0,0,93,95,5,23,0,0,94,85,1,0,0,0,94,86,1,0,0,0,94,87,1,0,0,0,
+        94,88,1,0,0,0,94,89,1,0,0,0,94,90,1,0,0,0,94,91,1,0,0,0,94,92,1,
+        0,0,0,95,13,1,0,0,0,96,98,5,16,0,0,97,96,1,0,0,0,97,98,1,0,0,0,98,
+        99,1,0,0,0,99,100,5,23,0,0,100,15,1,0,0,0,101,102,3,12,6,0,102,109,
+        3,14,7,0,103,104,5,17,0,0,104,105,3,12,6,0,105,106,3,14,7,0,106,
+        108,1,0,0,0,107,103,1,0,0,0,108,111,1,0,0,0,109,107,1,0,0,0,109,
+        110,1,0,0,0,110,17,1,0,0,0,111,109,1,0,0,0,112,116,5,18,0,0,113,
+        115,3,20,10,0,114,113,1,0,0,0,115,118,1,0,0,0,116,114,1,0,0,0,116,
+        117,1,0,0,0,117,119,1,0,0,0,118,116,1,0,0,0,119,120,5,19,0,0,120,
+        19,1,0,0,0,121,122,5,23,0,0,122,131,5,2,0,0,123,124,5,20,0,0,124,
+        125,5,23,0,0,125,131,5,2,0,0,126,127,5,20,0,0,127,128,5,16,0,0,128,
+        129,5,23,0,0,129,131,5,2,0,0,130,121,1,0,0,0,130,123,1,0,0,0,130,
+        126,1,0,0,0,131,21,1,0,0,0,132,133,3,12,6,0,133,136,3,14,7,0,134,
+        135,5,21,0,0,135,137,3,24,12,0,136,134,1,0,0,0,136,137,1,0,0,0,137,
+        138,1,0,0,0,138,139,5,2,0,0,139,23,1,0,0,0,140,145,5,23,0,0,141,
+        142,5,22,0,0,142,144,5,23,0,0,143,141,1,0,0,0,144,147,1,0,0,0,145,
+        143,1,0,0,0,145,146,1,0,0,0,146,25,1,0,0,0,147,145,1,0,0,0,148,149,
+        5,15,0,0,149,150,5,23,0,0,150,151,3,18,9,0,151,152,5,2,0,0,152,27,
+        1,0,0,0,16,35,41,54,57,62,66,70,74,80,94,97,109,116,130,136,145
+    ]
+
+class CMODParser ( Parser ):
+
+    grammarFileName = "CMOD.g4"
+
+    atn = ATNDeserializer().deserialize(serializedATN())
+
+    decisionsToDFA = [ DFA(ds, i) for i, ds in enumerate(atn.decisionToState) ]
+
+    sharedContextCache = PredictionContextCache()
+
+    literalNames = [ "<INVALID>", "'module'", "';'", "'import'", "'/'", 
+                     "'export'", "'('", "')'", "'void'", "'char'", "'short'", 
+                     "'int'", "'long'", "'float'", "'double'", "'struct'", 
+                     "'*'", "','", "'{'", "'}'", "'type'", "'='", "'+'" ]
+
+    symbolicNames = [ "<INVALID>", "<INVALID>", "<INVALID>", "<INVALID>", 
+                      "<INVALID>", "<INVALID>", "<INVALID>", "<INVALID>", 
+                      "<INVALID>", "<INVALID>", "<INVALID>", "<INVALID>", 
+                      "<INVALID>", "<INVALID>", "<INVALID>", "<INVALID>", 
+                      "<INVALID>", "<INVALID>", "<INVALID>", "<INVALID>", 
+                      "<INVALID>", "<INVALID>", "<INVALID>", "Identifier", 
+                      "StringLiteral", "Whitespace", "Newline", "BlockComment", 
+                      "LineComment" ]
+
+    RULE_compilationUnit = 0
+    RULE_translationUnit = 1
+    RULE_moduleDeclaration = 2
+    RULE_importDeclaration = 3
+    RULE_externalDeclaration = 4
+    RULE_limitedFunctionDefinition = 5
+    RULE_limitedTypeSpecifier = 6
+    RULE_limitedDeclarator = 7
+    RULE_limitedParameterList = 8
+    RULE_limitedCompoundStatement = 9
+    RULE_limitedStatement = 10
+    RULE_limitedGlobal = 11
+    RULE_limitedInitializer = 12
+    RULE_limitedStruct = 13
+
+    ruleNames =  [ "compilationUnit", "translationUnit", "moduleDeclaration", 
+                   "importDeclaration", "externalDeclaration", "limitedFunctionDefinition", 
+                   "limitedTypeSpecifier", "limitedDeclarator", "limitedParameterList", 
+                   "limitedCompoundStatement", "limitedStatement", "limitedGlobal", 
+                   "limitedInitializer", "limitedStruct" ]
+
+    EOF = Token.EOF
+    T__0=1
+    T__1=2
+    T__2=3
+    T__3=4
+    T__4=5
+    T__5=6
+    T__6=7
+    T__7=8
+    T__8=9
+    T__9=10
+    T__10=11
+    T__11=12
+    T__12=13
+    T__13=14
+    T__14=15
+    T__15=16
+    T__16=17
+    T__17=18
+    T__18=19
+    T__19=20
+    T__20=21
+    T__21=22
+    Identifier=23
+    StringLiteral=24
+    Whitespace=25
+    Newline=26
+    BlockComment=27
+    LineComment=28
+
+    def __init__(self, input:TokenStream, output:TextIO = sys.stdout):
+        super().__init__(input, output)
+        self.checkVersion("4.13.2")
+        self._interp = ParserATNSimulator(self, self.atn, self.decisionsToDFA, self.sharedContextCache)
+        self._predicates = None
+
+
+
+
+    class CompilationUnitContext(ParserRuleContext):
+        __slots__ = 'parser'
+
+        def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1):
+            super().__init__(parent, invokingState)
+            self.parser = parser
+
+        def translationUnit(self):
+            return self.getTypedRuleContext(CMODParser.TranslationUnitContext,0)
+
+
+        def EOF(self):
+            return self.getToken(CMODParser.EOF, 0)
+
+        def getRuleIndex(self):
+            return CMODParser.RULE_compilationUnit
+
+        def enterRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "enterCompilationUnit" ):
+                listener.enterCompilationUnit(self)
+
+        def exitRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "exitCompilationUnit" ):
+                listener.exitCompilationUnit(self)
+
+
+
+
+    def compilationUnit(self):
+
+        localctx = CMODParser.CompilationUnitContext(self, self._ctx, self.state)
+        self.enterRule(localctx, 0, self.RULE_compilationUnit)
+        try:
+            self.enterOuterAlt(localctx, 1)
+            self.state = 28
+            self.translationUnit()
+            self.state = 29
+            self.match(CMODParser.EOF)
+        except RecognitionException as re:
+            localctx.exception = re
+            self._errHandler.reportError(self, re)
+            self._errHandler.recover(self, re)
+        finally:
+            self.exitRule()
+        return localctx
+
+
+    class TranslationUnitContext(ParserRuleContext):
+        __slots__ = 'parser'
+
+        def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1):
+            super().__init__(parent, invokingState)
+            self.parser = parser
+
+        def moduleDeclaration(self):
+            return self.getTypedRuleContext(CMODParser.ModuleDeclarationContext,0)
+
+
+        def importDeclaration(self, i:int=None):
+            if i is None:
+                return self.getTypedRuleContexts(CMODParser.ImportDeclarationContext)
+            else:
+                return self.getTypedRuleContext(CMODParser.ImportDeclarationContext,i)
+
+
+        def externalDeclaration(self, i:int=None):
+            if i is None:
+                return self.getTypedRuleContexts(CMODParser.ExternalDeclarationContext)
+            else:
+                return self.getTypedRuleContext(CMODParser.ExternalDeclarationContext,i)
+
+
+        def getRuleIndex(self):
+            return CMODParser.RULE_translationUnit
+
+        def enterRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "enterTranslationUnit" ):
+                listener.enterTranslationUnit(self)
+
+        def exitRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "exitTranslationUnit" ):
+                listener.exitTranslationUnit(self)
+
+
+
+
+    def translationUnit(self):
+
+        localctx = CMODParser.TranslationUnitContext(self, self._ctx, self.state)
+        self.enterRule(localctx, 2, self.RULE_translationUnit)
+        self._la = 0 # Token type
+        try:
+            self.enterOuterAlt(localctx, 1)
+            self.state = 31
+            self.moduleDeclaration()
+            self.state = 35
+            self._errHandler.sync(self)
+            _la = self._input.LA(1)
+            while _la==3:
+                self.state = 32
+                self.importDeclaration()
+                self.state = 37
+                self._errHandler.sync(self)
+                _la = self._input.LA(1)
+
+            self.state = 41
+            self._errHandler.sync(self)
+            _la = self._input.LA(1)
+            while (((_la) & ~0x3f) == 0 and ((1 << _la) & 65316) != 0):
+                self.state = 38
+                self.externalDeclaration()
+                self.state = 43
+                self._errHandler.sync(self)
+                _la = self._input.LA(1)
+
+        except RecognitionException as re:
+            localctx.exception = re
+            self._errHandler.reportError(self, re)
+            self._errHandler.recover(self, re)
+        finally:
+            self.exitRule()
+        return localctx
+
+
+    class ModuleDeclarationContext(ParserRuleContext):
+        __slots__ = 'parser'
+
+        def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1):
+            super().__init__(parent, invokingState)
+            self.parser = parser
+
+
+        def getRuleIndex(self):
+            return CMODParser.RULE_moduleDeclaration
+
+        def enterRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "enterModuleDeclaration" ):
+                listener.enterModuleDeclaration(self)
+
+        def exitRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "exitModuleDeclaration" ):
+                listener.exitModuleDeclaration(self)
+
+
+
+
+    def moduleDeclaration(self):
+
+        localctx = CMODParser.ModuleDeclarationContext(self, self._ctx, self.state)
+        self.enterRule(localctx, 4, self.RULE_moduleDeclaration)
+        try:
+            self.enterOuterAlt(localctx, 1)
+            self.state = 44
+            self.match(CMODParser.T__0)
+            self.state = 45
+            self.match(CMODParser.T__1)
+        except RecognitionException as re:
+            localctx.exception = re
+            self._errHandler.reportError(self, re)
+            self._errHandler.recover(self, re)
+        finally:
+            self.exitRule()
+        return localctx
+
+
+    class ImportDeclarationContext(ParserRuleContext):
+        __slots__ = 'parser'
+
+        def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1):
+            super().__init__(parent, invokingState)
+            self.parser = parser
+
+        def StringLiteral(self):
+            return self.getToken(CMODParser.StringLiteral, 0)
+
+        def Identifier(self, i:int=None):
+            if i is None:
+                return self.getTokens(CMODParser.Identifier)
+            else:
+                return self.getToken(CMODParser.Identifier, i)
+
+        def getRuleIndex(self):
+            return CMODParser.RULE_importDeclaration
+
+        def enterRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "enterImportDeclaration" ):
+                listener.enterImportDeclaration(self)
+
+        def exitRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "exitImportDeclaration" ):
+                listener.exitImportDeclaration(self)
+
+
+
+
+    def importDeclaration(self):
+
+        localctx = CMODParser.ImportDeclarationContext(self, self._ctx, self.state)
+        self.enterRule(localctx, 6, self.RULE_importDeclaration)
+        self._la = 0 # Token type
+        try:
+            self.enterOuterAlt(localctx, 1)
+            self.state = 47
+            self.match(CMODParser.T__2)
+            self.state = 57
+            self._errHandler.sync(self)
+            token = self._input.LA(1)
+            if token in [24]:
+                self.state = 48
+                self.match(CMODParser.StringLiteral)
+                pass
+            elif token in [23]:
+                self.state = 49
+                self.match(CMODParser.Identifier)
+                self.state = 54
+                self._errHandler.sync(self)
+                _la = self._input.LA(1)
+                while _la==4:
+                    self.state = 50
+                    self.match(CMODParser.T__3)
+                    self.state = 51
+                    self.match(CMODParser.Identifier)
+                    self.state = 56
+                    self._errHandler.sync(self)
+                    _la = self._input.LA(1)
+
+                pass
+            else:
+                raise NoViableAltException(self)
+
+            self.state = 59
+            self.match(CMODParser.T__1)
+        except RecognitionException as re:
+            localctx.exception = re
+            self._errHandler.reportError(self, re)
+            self._errHandler.recover(self, re)
+        finally:
+            self.exitRule()
+        return localctx
+
+
+    class ExternalDeclarationContext(ParserRuleContext):
+        __slots__ = 'parser'
+
+        def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1):
+            super().__init__(parent, invokingState)
+            self.parser = parser
+
+        def limitedFunctionDefinition(self):
+            return self.getTypedRuleContext(CMODParser.LimitedFunctionDefinitionContext,0)
+
+
+        def limitedGlobal(self):
+            return self.getTypedRuleContext(CMODParser.LimitedGlobalContext,0)
+
+
+        def limitedStruct(self):
+            return self.getTypedRuleContext(CMODParser.LimitedStructContext,0)
+
+
+        def getRuleIndex(self):
+            return CMODParser.RULE_externalDeclaration
+
+        def enterRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "enterExternalDeclaration" ):
+                listener.enterExternalDeclaration(self)
+
+        def exitRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "exitExternalDeclaration" ):
+                listener.exitExternalDeclaration(self)
+
+
+
+
+    def externalDeclaration(self):
+
+        localctx = CMODParser.ExternalDeclarationContext(self, self._ctx, self.state)
+        self.enterRule(localctx, 8, self.RULE_externalDeclaration)
+        self._la = 0 # Token type
+        try:
+            self.state = 74
+            self._errHandler.sync(self)
+            la_ = self._interp.adaptivePredict(self._input,7,self._ctx)
+            if la_ == 1:
+                self.enterOuterAlt(localctx, 1)
+                self.state = 62
+                self._errHandler.sync(self)
+                _la = self._input.LA(1)
+                if _la==5:
+                    self.state = 61
+                    self.match(CMODParser.T__4)
+
+
+                self.state = 64
+                self.limitedFunctionDefinition()
+                pass
+
+            elif la_ == 2:
+                self.enterOuterAlt(localctx, 2)
+                self.state = 66
+                self._errHandler.sync(self)
+                _la = self._input.LA(1)
+                if _la==5:
+                    self.state = 65
+                    self.match(CMODParser.T__4)
+
+
+                self.state = 68
+                self.limitedGlobal()
+                pass
+
+            elif la_ == 3:
+                self.enterOuterAlt(localctx, 3)
+                self.state = 70
+                self._errHandler.sync(self)
+                _la = self._input.LA(1)
+                if _la==5:
+                    self.state = 69
+                    self.match(CMODParser.T__4)
+
+
+                self.state = 72
+                self.limitedStruct()
+                pass
+
+            elif la_ == 4:
+                self.enterOuterAlt(localctx, 4)
+                self.state = 73
+                self.match(CMODParser.T__1)
+                pass
+
+
+        except RecognitionException as re:
+            localctx.exception = re
+            self._errHandler.reportError(self, re)
+            self._errHandler.recover(self, re)
+        finally:
+            self.exitRule()
+        return localctx
+
+
+    class LimitedFunctionDefinitionContext(ParserRuleContext):
+        __slots__ = 'parser'
+
+        def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1):
+            super().__init__(parent, invokingState)
+            self.parser = parser
+
+        def limitedTypeSpecifier(self):
+            return self.getTypedRuleContext(CMODParser.LimitedTypeSpecifierContext,0)
+
+
+        def limitedDeclarator(self):
+            return self.getTypedRuleContext(CMODParser.LimitedDeclaratorContext,0)
+
+
+        def limitedCompoundStatement(self):
+            return self.getTypedRuleContext(CMODParser.LimitedCompoundStatementContext,0)
+
+
+        def limitedParameterList(self):
+            return self.getTypedRuleContext(CMODParser.LimitedParameterListContext,0)
+
+
+        def getRuleIndex(self):
+            return CMODParser.RULE_limitedFunctionDefinition
+
+        def enterRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "enterLimitedFunctionDefinition" ):
+                listener.enterLimitedFunctionDefinition(self)
+
+        def exitRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "exitLimitedFunctionDefinition" ):
+                listener.exitLimitedFunctionDefinition(self)
+
+
+
+
+    def limitedFunctionDefinition(self):
+
+        localctx = CMODParser.LimitedFunctionDefinitionContext(self, self._ctx, self.state)
+        self.enterRule(localctx, 10, self.RULE_limitedFunctionDefinition)
+        self._la = 0 # Token type
+        try:
+            self.enterOuterAlt(localctx, 1)
+            self.state = 76
+            self.limitedTypeSpecifier()
+            self.state = 77
+            self.limitedDeclarator()
+            self.state = 78
+            self.match(CMODParser.T__5)
+            self.state = 80
+            self._errHandler.sync(self)
+            _la = self._input.LA(1)
+            if (((_la) & ~0x3f) == 0 and ((1 << _la) & 65280) != 0):
+                self.state = 79
+                self.limitedParameterList()
+
+
+            self.state = 82
+            self.match(CMODParser.T__6)
+            self.state = 83
+            self.limitedCompoundStatement()
+        except RecognitionException as re:
+            localctx.exception = re
+            self._errHandler.reportError(self, re)
+            self._errHandler.recover(self, re)
+        finally:
+            self.exitRule()
+        return localctx
+
+
+    class LimitedTypeSpecifierContext(ParserRuleContext):
+        __slots__ = 'parser'
+
+        def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1):
+            super().__init__(parent, invokingState)
+            self.parser = parser
+
+        def Identifier(self):
+            return self.getToken(CMODParser.Identifier, 0)
+
+        def getRuleIndex(self):
+            return CMODParser.RULE_limitedTypeSpecifier
+
+        def enterRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "enterLimitedTypeSpecifier" ):
+                listener.enterLimitedTypeSpecifier(self)
+
+        def exitRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "exitLimitedTypeSpecifier" ):
+                listener.exitLimitedTypeSpecifier(self)
+
+
+
+
+    def limitedTypeSpecifier(self):
+
+        localctx = CMODParser.LimitedTypeSpecifierContext(self, self._ctx, self.state)
+        self.enterRule(localctx, 12, self.RULE_limitedTypeSpecifier)
+        try:
+            self.state = 94
+            self._errHandler.sync(self)
+            token = self._input.LA(1)
+            if token in [8]:
+                self.enterOuterAlt(localctx, 1)
+                self.state = 85
+                self.match(CMODParser.T__7)
+                pass
+            elif token in [9]:
+                self.enterOuterAlt(localctx, 2)
+                self.state = 86
+                self.match(CMODParser.T__8)
+                pass
+            elif token in [10]:
+                self.enterOuterAlt(localctx, 3)
+                self.state = 87
+                self.match(CMODParser.T__9)
+                pass
+            elif token in [11]:
+                self.enterOuterAlt(localctx, 4)
+                self.state = 88
+                self.match(CMODParser.T__10)
+                pass
+            elif token in [12]:
+                self.enterOuterAlt(localctx, 5)
+                self.state = 89
+                self.match(CMODParser.T__11)
+                pass
+            elif token in [13]:
+                self.enterOuterAlt(localctx, 6)
+                self.state = 90
+                self.match(CMODParser.T__12)
+                pass
+            elif token in [14]:
+                self.enterOuterAlt(localctx, 7)
+                self.state = 91
+                self.match(CMODParser.T__13)
+                pass
+            elif token in [15]:
+                self.enterOuterAlt(localctx, 8)
+                self.state = 92
+                self.match(CMODParser.T__14)
+                self.state = 93
+                self.match(CMODParser.Identifier)
+                pass
+            else:
+                raise NoViableAltException(self)
+
+        except RecognitionException as re:
+            localctx.exception = re
+            self._errHandler.reportError(self, re)
+            self._errHandler.recover(self, re)
+        finally:
+            self.exitRule()
+        return localctx
+
+
+    class LimitedDeclaratorContext(ParserRuleContext):
+        __slots__ = 'parser'
+
+        def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1):
+            super().__init__(parent, invokingState)
+            self.parser = parser
+
+        def Identifier(self):
+            return self.getToken(CMODParser.Identifier, 0)
+
+        def getRuleIndex(self):
+            return CMODParser.RULE_limitedDeclarator
+
+        def enterRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "enterLimitedDeclarator" ):
+                listener.enterLimitedDeclarator(self)
+
+        def exitRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "exitLimitedDeclarator" ):
+                listener.exitLimitedDeclarator(self)
+
+
+
+
+    def limitedDeclarator(self):
+
+        localctx = CMODParser.LimitedDeclaratorContext(self, self._ctx, self.state)
+        self.enterRule(localctx, 14, self.RULE_limitedDeclarator)
+        self._la = 0 # Token type
+        try:
+            self.enterOuterAlt(localctx, 1)
+            self.state = 97
+            self._errHandler.sync(self)
+            _la = self._input.LA(1)
+            if _la==16:
+                self.state = 96
+                self.match(CMODParser.T__15)
+
+
+            self.state = 99
+            self.match(CMODParser.Identifier)
+        except RecognitionException as re:
+            localctx.exception = re
+            self._errHandler.reportError(self, re)
+            self._errHandler.recover(self, re)
+        finally:
+            self.exitRule()
+        return localctx
+
+
+    class LimitedParameterListContext(ParserRuleContext):
+        __slots__ = 'parser'
+
+        def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1):
+            super().__init__(parent, invokingState)
+            self.parser = parser
+
+        def limitedTypeSpecifier(self, i:int=None):
+            if i is None:
+                return self.getTypedRuleContexts(CMODParser.LimitedTypeSpecifierContext)
+            else:
+                return self.getTypedRuleContext(CMODParser.LimitedTypeSpecifierContext,i)
+
+
+        def limitedDeclarator(self, i:int=None):
+            if i is None:
+                return self.getTypedRuleContexts(CMODParser.LimitedDeclaratorContext)
+            else:
+                return self.getTypedRuleContext(CMODParser.LimitedDeclaratorContext,i)
+
+
+        def getRuleIndex(self):
+            return CMODParser.RULE_limitedParameterList
+
+        def enterRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "enterLimitedParameterList" ):
+                listener.enterLimitedParameterList(self)
+
+        def exitRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "exitLimitedParameterList" ):
+                listener.exitLimitedParameterList(self)
+
+
+
+
+    def limitedParameterList(self):
+
+        localctx = CMODParser.LimitedParameterListContext(self, self._ctx, self.state)
+        self.enterRule(localctx, 16, self.RULE_limitedParameterList)
+        self._la = 0 # Token type
+        try:
+            self.enterOuterAlt(localctx, 1)
+            self.state = 101
+            self.limitedTypeSpecifier()
+            self.state = 102
+            self.limitedDeclarator()
+            self.state = 109
+            self._errHandler.sync(self)
+            _la = self._input.LA(1)
+            while _la==17:
+                self.state = 103
+                self.match(CMODParser.T__16)
+                self.state = 104
+                self.limitedTypeSpecifier()
+                self.state = 105
+                self.limitedDeclarator()
+                self.state = 111
+                self._errHandler.sync(self)
+                _la = self._input.LA(1)
+
+        except RecognitionException as re:
+            localctx.exception = re
+            self._errHandler.reportError(self, re)
+            self._errHandler.recover(self, re)
+        finally:
+            self.exitRule()
+        return localctx
+
+
+    class LimitedCompoundStatementContext(ParserRuleContext):
+        __slots__ = 'parser'
+
+        def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1):
+            super().__init__(parent, invokingState)
+            self.parser = parser
+
+        def limitedStatement(self, i:int=None):
+            if i is None:
+                return self.getTypedRuleContexts(CMODParser.LimitedStatementContext)
+            else:
+                return self.getTypedRuleContext(CMODParser.LimitedStatementContext,i)
+
+
+        def getRuleIndex(self):
+            return CMODParser.RULE_limitedCompoundStatement
+
+        def enterRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "enterLimitedCompoundStatement" ):
+                listener.enterLimitedCompoundStatement(self)
+
+        def exitRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "exitLimitedCompoundStatement" ):
+                listener.exitLimitedCompoundStatement(self)
+
+
+
+
+    def limitedCompoundStatement(self):
+
+        localctx = CMODParser.LimitedCompoundStatementContext(self, self._ctx, self.state)
+        self.enterRule(localctx, 18, self.RULE_limitedCompoundStatement)
+        self._la = 0 # Token type
+        try:
+            self.enterOuterAlt(localctx, 1)
+            self.state = 112
+            self.match(CMODParser.T__17)
+            self.state = 116
+            self._errHandler.sync(self)
+            _la = self._input.LA(1)
+            while _la==20 or _la==23:
+                self.state = 113
+                self.limitedStatement()
+                self.state = 118
+                self._errHandler.sync(self)
+                _la = self._input.LA(1)
+
+            self.state = 119
+            self.match(CMODParser.T__18)
+        except RecognitionException as re:
+            localctx.exception = re
+            self._errHandler.reportError(self, re)
+            self._errHandler.recover(self, re)
+        finally:
+            self.exitRule()
+        return localctx
+
+
+    class LimitedStatementContext(ParserRuleContext):
+        __slots__ = 'parser'
+
+        def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1):
+            super().__init__(parent, invokingState)
+            self.parser = parser
+
+        def Identifier(self):
+            return self.getToken(CMODParser.Identifier, 0)
+
+        def getRuleIndex(self):
+            return CMODParser.RULE_limitedStatement
+
+        def enterRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "enterLimitedStatement" ):
+                listener.enterLimitedStatement(self)
+
+        def exitRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "exitLimitedStatement" ):
+                listener.exitLimitedStatement(self)
+
+
+
+
+    def limitedStatement(self):
+
+        localctx = CMODParser.LimitedStatementContext(self, self._ctx, self.state)
+        self.enterRule(localctx, 20, self.RULE_limitedStatement)
+        try:
+            self.state = 130
+            self._errHandler.sync(self)
+            la_ = self._interp.adaptivePredict(self._input,13,self._ctx)
+            if la_ == 1:
+                self.enterOuterAlt(localctx, 1)
+                self.state = 121
+                self.match(CMODParser.Identifier)
+                self.state = 122
+                self.match(CMODParser.T__1)
+                pass
+
+            elif la_ == 2:
+                self.enterOuterAlt(localctx, 2)
+                self.state = 123
+                self.match(CMODParser.T__19)
+                self.state = 124
+                self.match(CMODParser.Identifier)
+                self.state = 125
+                self.match(CMODParser.T__1)
+                pass
+
+            elif la_ == 3:
+                self.enterOuterAlt(localctx, 3)
+                self.state = 126
+                self.match(CMODParser.T__19)
+                self.state = 127
+                self.match(CMODParser.T__15)
+                self.state = 128
+                self.match(CMODParser.Identifier)
+                self.state = 129
+                self.match(CMODParser.T__1)
+                pass
+
+
+        except RecognitionException as re:
+            localctx.exception = re
+            self._errHandler.reportError(self, re)
+            self._errHandler.recover(self, re)
+        finally:
+            self.exitRule()
+        return localctx
+
+
+    class LimitedGlobalContext(ParserRuleContext):
+        __slots__ = 'parser'
+
+        def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1):
+            super().__init__(parent, invokingState)
+            self.parser = parser
+
+        def limitedTypeSpecifier(self):
+            return self.getTypedRuleContext(CMODParser.LimitedTypeSpecifierContext,0)
+
+
+        def limitedDeclarator(self):
+            return self.getTypedRuleContext(CMODParser.LimitedDeclaratorContext,0)
+
+
+        def limitedInitializer(self):
+            return self.getTypedRuleContext(CMODParser.LimitedInitializerContext,0)
+
+
+        def getRuleIndex(self):
+            return CMODParser.RULE_limitedGlobal
+
+        def enterRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "enterLimitedGlobal" ):
+                listener.enterLimitedGlobal(self)
+
+        def exitRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "exitLimitedGlobal" ):
+                listener.exitLimitedGlobal(self)
+
+
+
+
+    def limitedGlobal(self):
+
+        localctx = CMODParser.LimitedGlobalContext(self, self._ctx, self.state)
+        self.enterRule(localctx, 22, self.RULE_limitedGlobal)
+        self._la = 0 # Token type
+        try:
+            self.enterOuterAlt(localctx, 1)
+            self.state = 132
+            self.limitedTypeSpecifier()
+            self.state = 133
+            self.limitedDeclarator()
+            self.state = 136
+            self._errHandler.sync(self)
+            _la = self._input.LA(1)
+            if _la==21:
+                self.state = 134
+                self.match(CMODParser.T__20)
+                self.state = 135
+                self.limitedInitializer()
+
+
+            self.state = 138
+            self.match(CMODParser.T__1)
+        except RecognitionException as re:
+            localctx.exception = re
+            self._errHandler.reportError(self, re)
+            self._errHandler.recover(self, re)
+        finally:
+            self.exitRule()
+        return localctx
+
+
+    class LimitedInitializerContext(ParserRuleContext):
+        __slots__ = 'parser'
+
+        def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1):
+            super().__init__(parent, invokingState)
+            self.parser = parser
+
+        def Identifier(self, i:int=None):
+            if i is None:
+                return self.getTokens(CMODParser.Identifier)
+            else:
+                return self.getToken(CMODParser.Identifier, i)
+
+        def getRuleIndex(self):
+            return CMODParser.RULE_limitedInitializer
+
+        def enterRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "enterLimitedInitializer" ):
+                listener.enterLimitedInitializer(self)
+
+        def exitRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "exitLimitedInitializer" ):
+                listener.exitLimitedInitializer(self)
+
+
+
+
+    def limitedInitializer(self):
+
+        localctx = CMODParser.LimitedInitializerContext(self, self._ctx, self.state)
+        self.enterRule(localctx, 24, self.RULE_limitedInitializer)
+        self._la = 0 # Token type
+        try:
+            self.enterOuterAlt(localctx, 1)
+            self.state = 140
+            self.match(CMODParser.Identifier)
+            self.state = 145
+            self._errHandler.sync(self)
+            _la = self._input.LA(1)
+            while _la==22:
+                self.state = 141
+                self.match(CMODParser.T__21)
+                self.state = 142
+                self.match(CMODParser.Identifier)
+                self.state = 147
+                self._errHandler.sync(self)
+                _la = self._input.LA(1)
+
+        except RecognitionException as re:
+            localctx.exception = re
+            self._errHandler.reportError(self, re)
+            self._errHandler.recover(self, re)
+        finally:
+            self.exitRule()
+        return localctx
+
+
+    class LimitedStructContext(ParserRuleContext):
+        __slots__ = 'parser'
+
+        def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1):
+            super().__init__(parent, invokingState)
+            self.parser = parser
+
+        def Identifier(self):
+            return self.getToken(CMODParser.Identifier, 0)
+
+        def limitedCompoundStatement(self):
+            return self.getTypedRuleContext(CMODParser.LimitedCompoundStatementContext,0)
+
+
+        def getRuleIndex(self):
+            return CMODParser.RULE_limitedStruct
+
+        def enterRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "enterLimitedStruct" ):
+                listener.enterLimitedStruct(self)
+
+        def exitRule(self, listener:ParseTreeListener):
+            if hasattr( listener, "exitLimitedStruct" ):
+                listener.exitLimitedStruct(self)
+
+
+
+
+    def limitedStruct(self):
+
+        localctx = CMODParser.LimitedStructContext(self, self._ctx, self.state)
+        self.enterRule(localctx, 26, self.RULE_limitedStruct)
+        try:
+            self.enterOuterAlt(localctx, 1)
+            self.state = 148
+            self.match(CMODParser.T__14)
+            self.state = 149
+            self.match(CMODParser.Identifier)
+            self.state = 150
+            self.limitedCompoundStatement()
+            self.state = 151
+            self.match(CMODParser.T__1)
+        except RecognitionException as re:
+            localctx.exception = re
+            self._errHandler.reportError(self, re)
+            self._errHandler.recover(self, re)
+        finally:
+            self.exitRule()
+        return localctx
+
+
+
+
+
Index: doc/proposals/modules-alvin/1_stitched_modules/requirements.txt
===================================================================
--- doc/proposals/modules-alvin/1_stitched_modules/requirements.txt	(revision 3151bc098c7455c35a93a8f6de9f47dc4f0a07eb)
+++ doc/proposals/modules-alvin/1_stitched_modules/requirements.txt	(revision 3151bc098c7455c35a93a8f6de9f47dc4f0a07eb)
@@ -0,0 +1,1 @@
+antlr4-python3-runtime==4.13.2
Index: doc/proposals/modules-alvin/1_stitched_modules/stitched_modules.md
===================================================================
--- doc/proposals/modules-alvin/1_stitched_modules/stitched_modules.md	(revision 3151bc098c7455c35a93a8f6de9f47dc4f0a07eb)
+++ doc/proposals/modules-alvin/1_stitched_modules/stitched_modules.md	(revision 3151bc098c7455c35a93a8f6de9f47dc4f0a07eb)
@@ -0,0 +1,124 @@
+# Stitched modules
+
+## Background context
+
+C doesn't have modules -- instead, C relies on the programmer (+ preprocessor) to insert the references to any symbols that are defined in other files. This is because the C compiler only processes one translation unit from top to bottom, so you have to give it everything, and in the correct order.
+
+So our C module system simply analyzes other modules and extracts any imported information to give to the compiler, right? Yes, but it's a bit tricky because C is a systems programming language, which means we care a lot about how our code is compiled. An object-oriented approach hides a class' implementation behind a pointer and a vtable (also a pointer), so importers can use a class without even knowing its size. This doesn't work for C because it has unboxed types, so we need to expose information to the compiler.
+
+### A previous attempt
+
+A previous attempt at C modules used "type stubs", meaning that each exported type would generate a "stub" type with only size and alignment information. Any function that returned the exported type would return the "stub" type instead, so importers wouldn't need to know any implementation details unless they imported the actual type (which would use type-punning to convert between the two). This approach unfortunately doesn't work in C because type-punning breaks strict aliasing rules, and the C spec allows small structs to be unpacked when used as arguments into functions. Additionally, extracting size and alignment information can require analyzing the entire codebase -- if we have to do all that to make just unboxed types work, perhaps there are better options.
+
+### Other languages
+
+Let's take a look at some other systems programming languages to see how they do it. C and C++ use header files, as described above. C++20 modules need to be compiled before they can be imported, which makes them acyclic. Rust compiles an entire crate all at once, so modules are essentially namespaces, and modules can import freely within a crate. Zig modules are implicitly structs, and are used by assigning the import to a name.
+
+C and C++ header files lead to a lot of manual module management, where the programmer has to ensure the .h and its corresponding .c file stay in sync. It should be possible to condense this workflow into a single file without any practical loss of functionality. C++20 modules are acyclic, forcing any mutually recursive structures into the same module -- this doesn't work with the granularity of .c/.h files, which frequently share declarations with each other. Rust modules rely on whole-crate compilation, which clashes with the C philosophy of separate compilation. Zig modules share many similarities with this prototype, and present some interesting avenues for further development. As such, we will discuss Zig modules after presenting the prototype.
+
+## The prototype
+
+The code for processing modules is in `Driver.py`, using the grammar in `CMOD.g4`. You can run it on files in `testing/` by following the `README.md`. We will now analyze what `Driver.py` is doing.
+
+`module_data` extracts top-level symbols from the input code, producing a type and variable symbol table (minus the imported symbols). Note that, while parsing C into an AST is context-sensitive (eg. `(a)*b` is a cast or a multiplication, depending on if `a` is a type), it is unambiguous outside of expressions. This means we can extract top-level symbol information from C files, and leave the rest for a later pass (here it is extracted into `used_names_*`, but it can be done right after the `module_input` step).
+
+Next, `module_input` combines the top-level symbols of a module with any imported symbols (which we can do because we have `module_data`) to produce the complete type and variable symbol table. Once this is done, you can parse the remaining expressions in the C file, which would produce a complete AST with the correct symbol references.
+
+Finally, `module_output` performs symbol renaming (so symbols are linked to the correct module), as well as performing a topological ordering (so needed symbols are defined before they are used). The symbol renaming uses a simple namespacing strategy, prepending the file path of the module (when read from the project root directory) to the name (see `full_name()`). The topological ordering takes into consideration whether a definition or declaration is needed, and is able to handle circular file imports. Note that this process allows types to depend on variables out-of-the-box, so inline functions can be supported without significant changes to the algorithm (mutually recursive inline functions may need to be handled by a special case).
+
+The code should be reasonably straightforward to understand, and is fairly robust. The one caveat is that overloading is not supported -- if a function and a variable have the same name, the code will pick one and silently overwrite the other.
+
+### An example
+
+Let's do a quick example to showcase the power of this algorithm:
+
+```
+// a.cmod       // b.cmod
+module;         module;
+import b;       import a;
+struct s1 {
+    type s2;    struct s2 {
+};
+struct s3 {         type s3;
+                };
+    type *s4;   struct s4 {
+};                  type s3;
+                };
+```
+
+This example has many dependencies from a to b, and vice versa. However, the module system can process this into:
+
+```
+// a.cmod (processed)
+struct b$$s4;
+struct a$$s3 {
+    type *b$$s4;
+};
+struct b$$s2 {
+    type a$$s3;
+};
+struct a$$s1 {
+    type b$$s2;
+};
+```
+
+### Design choices
+
+There are a number of design choices in this prototype, as well as ideas that I had in mind when creating this prototype, which are not critical to the functionality of this algorithm.
+
+* Imports follow the file system: Just like `#include`, we resolve modules by following the file system. Other languages have users specify module names, but for now it seemed unnecessarily complex.
+    * As such, the module declaration at the top of a module file (`module;`) does not take a name argument (this declaration would be used to distinguish a regular C file from a C module file).
+    * As seen in `testing/`, files with the same name as a folder exist outside of it (ie. `yesImports/` and `yesImports.cmod`). This is in line with Rust, which initially used `mod.rs` for folder-like files before using this strategy.
+* Symbol names are prefixed with the file path of the module, as read from the project root folder.
+* Imports automatically expand into module scope: The alternative is to have imports like `import "graph/node" as N;`. Doing so would require prefixing any symbols from "graph/node.cmod" (eg. `N.struct_1`). The prototype took the other approach to keep the language less verbose.
+    * The prototype ignores name clashes, but a full module system should give the ability to disambiguate. One idea is to use the module name (eg. `"../graph".struct_2`)
+* We use `import` and `export` keywords to control module visibility.
+* This isn't demonstrated in the grammar, but follows from the work in my previous attempt at modules (type stubs). The idea is that struct definitions are not visible unless imported. For example, if a module imports `struct struct_3 {struct struct_4 field_1;};` but does not import `struct struct_4`, it can access `field_1` but it cannot access any fields of `field_1`. This would work similarly to how, if `field_1` were a pointer, you don't have access to the struct.
+
+### Comparison with Zig
+
+Zig has separate compilation, cicular modules and no header files! This is what my module system is trying to do, so it's really worth taking a close look:
+* `@import` is like treating the file as a struct. You assign to a name and use it.
+    * This neatly unifies language concepts -- Zig's main feature is compile-time logic (`comptime`), and `@import` behaves like any other compile-time function.
+* Compile-time functions (`@import` works like one) are memoized, so importing twice leads to references to the same object (avoiding double-definitions).
+    * This may explain why they use module names instead of file paths; file paths change depending on the current directory, which messes with memoization.
+* The Zig compiler waits until a struct/function is used before analyzing its definition/declaration.
+    * This "lazy evalution" differs from my prototype, which performs "eager evaluation" of imports. The prototype does this partly because it's simpler to implement, but also because I need `module_input` in order to resolve parsing ambiguities.
+    * Using functions means analyzing function declarations, not their definition. If you want inline functions or constants, those are likely handled by the `comptime` feature. Cforall doesn't have such a feature and requires backwards compatibility with C, so we can't make this assumption. Thankfully, the prototype can be adapted to work for cases such as inline functions.
+* Zig has the philosophy of making things explicit: no implicit constructors/destructors, passing allocators into functions, etc. There is also no private struct fields (the idea being that when you're working low-level, you may need access to the internals). I think Cforall takes a different approach, using more powerful abstractions (potentially influenced by C++); however, I think Zig has a lot of merit in wanting to make things visible and tweakable by the programmer, and we could benefit from taking some of these ideas.
+
+### Ideas for future direction
+
+So with this insight, combined with the design choices section, what direction would I like to take this?
+* I still like the idea of resolving modules by following the file system. The fact that `import "std/array";` works similarly to `#include "std/array.h"` is really nice in my opinion.
+    * That being said, my current grammar also allows writing `import std/array;` , which I think is a mistake. The unquoted version should be reserved for if/when we support named modules, which would look like `module file_reader;` and `import file_reader;`
+* Unlike Zig, Cforall still needs to compile down to C code, so prefixing symbol names with the module name is still the most reasonable solution I can come up with that still works with existing C linkers.
+* I'm inspired by the way Zig assigns imports to a symbol, so I'd like to try having imports require the `as` keyword (eg. `import "graph/node" as N;`). If the programmer wants the import to be expanded into scope, they can use `with N;` or `import "graph/node" as *;`. This also resolves any nasty disambiguation syntax such as `"../graph".struct_2`.
+    * One of the struggles with this was that `import "graph/node" as N; import "graph/node" as M;` (in practice, this could happen through "diamond imports") would mean `N.struct_1` and `M.struct_1` need to refer to the same struct, without double-definition problems. With the concept of memoization, this turns out to be implementable.
+    * I concede that `N.struct_1` and `M.struct_1` isn't the nicest thing to deal with. Rust would write `"../graph".struct_2` as `super::graph.struct_2`, but I would like to stick with import names looking the same as `#include`. As a consolation, the meaning is not ambiguous, and this is arguably an edge case.
+    * This does increase the verbosity of the language, but it's arguably worth it for the increased readability. Note that Python, a language touted for its ease of use, works in a similar manner. Additionally, this renaming can be automated, so migrating existing systems shouldn't be a problem.
+* We use `import/export`, similar to C++20 modules. Rust uses `use/pub`, Zig uses `@import/pub`. For now, I don't see a need to change, and it's fairly simple to update in the future.
+* I'm quite conflicted on the idea that struct definitions (therefore its fields) should not be visible unless imported. While restricting field access is common in other languages, no language does it in the way I'm envisoning.
+    * By example: if I import `struct struct_5 foo() {...}` but I don't import `struct_5`, I should be able to use `foo()` (which would include assigning to a variable) but I can't access the fields of the return value. You only get the functionality that you import.
+    * The implementation problem: In C, in order to create a variable you need to specify its type. So you'll have to provide some way to expose the name `struct_5` to the importer. If you do that, why can't you give me the fields too?
+    * The useability problem: The ability to access the fields of a returned value can be seen as necessary in order to properly use a function (eg. function returns named tuple). So you're forcing the programmer to do extra import/export management for not much practical gain. Additionally, this isn't very "C-like", because in regular C you would need to provide the struct definition here.
+    * You can think of this concept as "opaque types, but from the importer's side". The function itself does nothing to hide the fact it's using `struct_5`, but the importer cannot use `struct_5` because it didn't import it. Pretty much all other languages (eg. Scala, Swift) put the opaque type on the exporter's side. In comparison, my system seems unnecessarily pedantic. If we want to consider restricting field access, public/private fields also provide better granularity (we might be able to leverage "tagged exports", described below).
+        * It's also worth asking if hiding struct information is the right thing. Zig chooses not to have private fields, taking the philosophy that low-level often needs to reach into the internals of a struct in order to produce composable abstraction layers. Something I'm interested in knowing is: if I have a variable whose type has a field with a pointer to some other struct, can I access the other struct's fields? If you can, then it would be consistent between pointer and non-pointer fields.
+    * Ultimately, it might be best to abandon this idea, as it is pedantic for not enough practical benefit. Just let the programmer access the struct in the same way it's written in the function declaration.
+        * As an aside, trait information in Cforall might also be unnecessarily pedantic. Having to import a forall, trait, struct, and certain methods in order to make use of some polymorphic function seems a bit overkill (though I might be missing something).
+* Modules often need to expose different interfaces to different modules. For example, a thread module may need to expose more information to a garbage collection module than a regular module. The object-oriented technique of having "friend classes" is an all-or-nothing approach; it's not great because it lacks granularity. Instead, we can tag certain exports: the thread module uses `export(details) struct internals {...};` while the garbage collection module uses `import thread(+, details);` (the `+` referring to also wanting regular exports).
+    * I've never seen this in the wild before, but a quick search shows that Perl has some form of this in the form of `%EXPORT_TAGS`. I like my method of putting it directly on the symbol definition instead of a big array at the bottom of the file, though.
+
+## Future work
+
+* The current request is to generate headers from analyzing .c files. My general steps would be to:
+    * parse C code, extract necessary symbols (like `module_data` step).
+    * *(start with a simpler model, without inline functions or constants)*
+    * figure out what other code it's referencing (use `#include` to figure out where to look, like `module_input` step).
+    * Heavily cyclic symbol references requires breaking a single header into multiple parts. To start, we can assume modules are not cyclic and put an `#include` in the header when symbols from other files are used. Then we can see where the cycles are happening and prioritize those first.
+    * *tbh I'm not sure why you'd want to go back to using headers when the information is all gathered already -- you could just merge this logic into the compilation step. I think it's more for people who don't want to change anything about their code (use it more like a tool rather than changing their compiler). Perhaps it's a "gateway drug" to the full module system. It also could function as a "source of truth" for what the full module system should be doing.*
+* I want to take a closer look at Zig, actually run some code to validate my theories. Also look at some other "low-level languages".
+* Flesh out how the full C module system would work.
+    * I'd also need to look into implementing migration tooling (likely will be able to reuse functionality from previous steps)
+* Write thesis.
+* Graduate.
Index: doc/proposals/modules-alvin/1_stitched_modules/testing/noImports.cmod
===================================================================
--- doc/proposals/modules-alvin/1_stitched_modules/testing/noImports.cmod	(revision 3151bc098c7455c35a93a8f6de9f47dc4f0a07eb)
+++ doc/proposals/modules-alvin/1_stitched_modules/testing/noImports.cmod	(revision 3151bc098c7455c35a93a8f6de9f47dc4f0a07eb)
@@ -0,0 +1,31 @@
+module;
+
+export void fn_1() {}
+int fn_2(int a) {}
+struct struct_1 fn_3(struct struct_2 a, struct struct_3 *b) {
+    global_1;
+    type struct_4;
+    type *struct_5;
+}
+
+struct struct_1 {};
+export struct struct_2 {};
+struct struct_3 {
+    global_2;
+    type *struct_6;
+};
+struct struct_4 {
+    type struct_5;
+};
+export struct struct_5 {
+    type *struct_6;
+};
+struct struct_6 {
+    type struct_5;
+};
+
+int global_1;
+export int global_2 = global_3 + global_4 + global_1;
+int global_3 = global_5;
+struct struct_4 global_4;
+export struct struct_5 *global_5 = global_1;
Index: doc/proposals/modules-alvin/1_stitched_modules/testing/yesImports.cmod
===================================================================
--- doc/proposals/modules-alvin/1_stitched_modules/testing/yesImports.cmod	(revision 3151bc098c7455c35a93a8f6de9f47dc4f0a07eb)
+++ doc/proposals/modules-alvin/1_stitched_modules/testing/yesImports.cmod	(revision 3151bc098c7455c35a93a8f6de9f47dc4f0a07eb)
@@ -0,0 +1,16 @@
+module;
+
+import yesImports/a;
+import "yesImports/b";
+
+struct struct_1 {
+    // Uses b because it's exported (a isn't)
+    type struct_2;
+};
+
+export struct struct_4 {
+    // Uses a because it's exported (b isn't)
+    global_1;
+    // Uses a
+    type struct_5;
+};
Index: doc/proposals/modules-alvin/1_stitched_modules/testing/yesImports/a.cmod
===================================================================
--- doc/proposals/modules-alvin/1_stitched_modules/testing/yesImports/a.cmod	(revision 3151bc098c7455c35a93a8f6de9f47dc4f0a07eb)
+++ doc/proposals/modules-alvin/1_stitched_modules/testing/yesImports/a.cmod	(revision 3151bc098c7455c35a93a8f6de9f47dc4f0a07eb)
@@ -0,0 +1,25 @@
+module;
+
+import b;
+
+struct struct_2 {
+    // Uses a because own module shadows imported b
+    global_1;
+};
+export int global_1;
+
+int function_1() {
+    // This is not overloaded with b because they are never
+    // exported into the same space
+}
+
+export struct struct_5 {
+    // Uses b
+    type struct_6;
+    // Uses b
+    global_2;
+};
+export struct struct_7 {
+    // Uses b
+    type *struct_8;
+};
Index: doc/proposals/modules-alvin/1_stitched_modules/testing/yesImports/b.cmod
===================================================================
--- doc/proposals/modules-alvin/1_stitched_modules/testing/yesImports/b.cmod	(revision 3151bc098c7455c35a93a8f6de9f47dc4f0a07eb)
+++ doc/proposals/modules-alvin/1_stitched_modules/testing/yesImports/b.cmod	(revision 3151bc098c7455c35a93a8f6de9f47dc4f0a07eb)
@@ -0,0 +1,31 @@
+module;
+
+import a;
+import "../yesImports";
+
+export struct struct_2 {
+    // Uses b because own module shadows imported a
+    global_1;
+};
+int global_1;
+
+int function_1(struct struct_3 foo /* Uses b */) {
+    // Uses b because own module shadows imported a
+    global_1;
+}
+
+export struct struct_3 {
+    // Uses yesImports
+    type struct_4;
+};
+export int global_2;
+export struct struct_6 {
+    // Uses a
+    type struct_7;
+};
+export struct struct_8 {
+    // uses b
+    function_1;
+    // uses b
+    type struct_7;
+};
