Exemplo n.º 1
0
def _find_module_file(module_dir_list, module_name):
    #按目录查找
    for module_dir in module_dir_list:
        module_file_path_name = os.path.join(module_dir, module_name) + ".coc"
        if os.path.exists(module_file_path_name):
            return module_file_path_name
    cocc_common.exit("找不到模块:%s" % module_name)
Exemplo n.º 2
0
def parse_token_list(src_file):
    f = open(src_file)
    f.seek(0, os.SEEK_END)
    if f.tell() > 100 * 1024 ** 2:
        cocc_common.exit("源代码文件[%s]过大" % src_file)
    f.seek(0, os.SEEK_SET)
    line_list = f.read().splitlines()

    token_list = TokenList(src_file)
    in_comment = False
    for line_no, line in enumerate(line_list):
        line_no += 1

        if in_comment:
            #有未完的注释
            pos = line.find("*/")
            if pos < 0:
                #整行都是注释,忽略
                continue
            pos += 2
            in_comment = False
        else:
            pos = 0

        #解析当前行token
        while pos < len(line):
            #跳过空格
            while pos < len(line) and line[pos] in "\t\x20":
                pos += 1
            if pos >= len(line):
                #行结束
                break

            if line[pos : pos + 2] == "//":
                #单行注释,略过本行
                break
            if line[pos : pos + 2] == "/*":
                #块注释
                pos += 2
                comment_end_pos = line[pos :].find("*/")
                if comment_end_pos < 0:
                    #注释跨行了,设置标记略过本行
                    in_comment = True
                    break
                #注释在本行结束,跳过它
                pos += comment_end_pos + 2
                continue

            #解析token
            token, token_len = _parse_token(src_file, line_no, line, pos)
            token_list.append(token)
            pos += token_len

    if in_comment:
        _syntax_err(src_file, len(line_list), len(line_list[-1]), "存在未结束的块注释")

    token_list.join_str_literal()

    return token_list
Exemplo n.º 3
0
 def check_overload(self):
     for cls in self.class_map.itervalues():
         cls.check_overload()
     for name, func_list in self.func_map.iteritems():
         for i, func in enumerate(func_list):
             for other_func in func_list[i + 1 :]:
                 assert name == func.name == other_func.name
                 if _same_arg_map(func.arg_map, other_func.arg_map):
                     cocc_common.exit("模块'%s'的方法'%s'存在两个相同签名的重载" % (self.name, name))
Exemplo n.º 4
0
 def expand(self):
     if self.stat == self.STAT_EXPANDING:
         cocc_common.exit("'%s.%s'存在循环typedef" % (self.module.name, self.name))
     if self.stat == self.STAT_EXPANDED:
         return
     assert self.stat == self.STAT_TO_EXPAND
     self.stat = self.STAT_EXPANDING
     self.type = self._expand(self.type)
     self.stat = self.STAT_EXPANDED
Exemplo n.º 5
0
 def __init__(self, file_path_name):
     self.dir, file_name = os.path.split(file_path_name)
     assert file_name.endswith(".coc")
     self.name = file_name[: -4]
     self._precompile(file_path_name)
     if self.name == "__builtins":
         #内建模块需要做一些必要的检查
         if "String" not in self.class_map: #必须有String类
             cocc_common.exit("内建模块缺少String类")
         str_cls = self.class_map["String"]
         if "format" in str_cls.attr_map or "format" in str_cls.method_map:
             cocc_common.exit("String类的format方法属于内建保留方法,禁止显式定义")
Exemplo n.º 6
0
 def check_overload(self):
     for i, method in enumerate(self.construct_method):
         for other_method in self.construct_method[i + 1 :]:
             assert self.name == method.name == other_method.name
             if _same_arg_map(method.arg_map, other_method.arg_map):
                 cocc_common.exit("类'%s.%s'的构造方法存在两个相同签名的重载" % (self.module.name, cls.name))
                 
     for name, method_list in self.method_map.iteritems():
         for i, method in enumerate(method_list):
             for other_method in method_list[i + 1 :]:
                 assert name == method.name == other_method.name
                 if _same_arg_map(method.arg_map, other_method.arg_map):
                     cocc_common.exit("类'%s.%s'的方法'%s'存在两个相同签名的重载" % (self.module.name, cls.name, name))
Exemplo n.º 7
0
    def sub_class_check(self):
        if self.base_cls_type is None:
            return

        #构造继承链,同时检测循环继承、构造方法链是否能正常执行等
        inherit_list = [self]
        while True:
            new_base_cls_type = inherit_list[-1].base_cls_type
            if new_base_cls_type is None:
                break
            new_base_cls = new_base_cls_type.get_cls()
            if "final" in new_base_cls.decr_set:
                cocc_common.exit("类'%s.%s'继承了一个final类" % (self.module.name, cls.name))
            for cls in inherit_list:
                if cls is new_base_cls:
                    cocc_common.exit("类'%s.%s'循环继承" % (cls.module.name, cls.name))
            inherit_list.append(new_base_cls)
        del inherit_list[0]

        for attr in self.attr_map.itervalues():
            for base_cls in inherit_list:
                if attr.name in base_cls.method_map:
                    cocc_common.exit("类'%s.%s'的属性'%s'在基类'%s.%s'实现为方法" %
                                     (self.module.name, self.name, attr.name, base_cls.module.name, base_cls.name))

        for name, method_list in self.method_map.iteritems():
            for base_cls in inherit_list:
                if name in base_cls.attr_map:
                    cocc_common.exit("类'%s.%s'的方法'%s'在基类'%s.%s'实现为属性" %
                                     (self.module.name, self.name, name, base_cls.module.name, base_cls.name))
                if name in base_cls.method_map:
                    base_method_list = base_cls.method_map[name]
                    #对基类的每个方法,检查其在子类中的实现情况
                    for base_method in base_method_list:
                        match_count = 0
                        for method in method_list:
                            if _same_arg_map(base_method.arg_map, method.arg_map):
                                match_count += 1
                                if "final" in base_method.decr_set:
                                    cocc_common.exit("类'%s.%s'的方法'%s'在基类'%s.%s'中带final属性,不可覆盖" %
                                                     (self.module.name, self.name, method.name, base_cls.module.name, base_cls.name))
                                if method.access_ctrl != base_method.access_ctrl:
                                    cocc_common.exit("类'%s.%s'的方法'%s'定义修改了在基类'%s.%s'中定义的存取控制方式:从'%s'修改为'%s'" %
                                                     (self.module.name, self.name, method.name, base_cls.module.name, base_cls.name,
                                                      base_method.access_ctrl, method.access_ctrl))
                                if method.type != base_method.type:
                                    cocc_common.exit("类'%s.%s'的方法'%s'返回类型'%s'和其在基类'%s.%s'中定义的'%s'不同" %
                                                     (self.module.name, self.name, method.name, method.type, base_cls.module.name,
                                                      base_cls.name, base_method.type))
                        if match_count == 0:
                            cocc_common.warning("类'%s.%s'的方法'%s'隐藏了在基类'%s.%s'中的其他重载" %
                                                (self.module.name, self.name, method.name, base_cls.module.name, base_cls.name))
                        else:
                            assert match_count == 1
Exemplo n.º 8
0
 def syntax_err(self, msg = ""):
     cocc_common.exit("语法错误:文件[%s]行[%d]列[%d]%s" % (self.src_file, self.line_no, self.pos + 1, msg))
Exemplo n.º 9
0
def _syntax_err(src_file, line_no, pos, msg):
    cocc_common.exit("语法错误:文件[%s]行[%d]列[%d]%s" % (src_file, line_no, pos + 1, msg))
Exemplo n.º 10
0
 def peek(self):
     if not self:
         cocc_common.exit("语法错误:文件[%s]代码意外结束" % self.src_file)
     return self.l[self.i]
Exemplo n.º 11
0
def main():
    #解析命令行参数
    opt_list, args = getopt.getopt(sys.argv[1 :], "", [])

    if len(args) != 1:
        _show_usage_and_exit()

    #通用目录
    compiler_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
    lib_dir = os.path.join(os.path.dirname(compiler_dir), "lib")

    #预处理builtins等模块
    cocc_module.builtins_module = cocc_module.Module(os.path.join(lib_dir, "__builtins.coc"))
    cocc_module.module_map[cocc_module.builtins_module.name] = cocc_module.builtins_module
    cocc_module.module_map["concurrent"] = cocc_module.Module(os.path.join(lib_dir, "concurrent.coc"))

    #先处理主模块
    main_file_path_name = os.path.abspath(args[0])
    if not main_file_path_name.endswith(".coc"):
        cocc_common.exit("非法的主模块文件名[%s]" % main_file_path_name)
    if not os.path.exists(main_file_path_name):
        cocc_common.exit("找不到主模块文件[%s]" % main_file_path_name)
    main_module = cocc_module.Module(main_file_path_name)
    cocc_module.module_map[main_module.name] = main_module

    #模块查找的目录列表
    src_dir = os.path.dirname(main_file_path_name)
    module_dir_list = [src_dir, lib_dir]

    #找到并预编译所有涉及到的模块
    compiling_set = main_module.dep_module_set #需要预编译的模块名集合
    while compiling_set:
        new_compiling_set = set()
        for module_name in compiling_set:
            if module_name in cocc_module.module_map:
                #已预编译过
                continue
            module_file_path_name = _find_module_file(module_dir_list, module_name)
            cocc_module.module_map[module_name] = m = cocc_module.Module(module_file_path_name)
            new_compiling_set |= m.dep_module_set
        compiling_set = new_compiling_set

    #先扩展嵌套typedef,然后单独对typedef的type进行check
    cocc_module.builtins_module.expand_typedef()
    for m in cocc_module.module_map.itervalues():
        if m is not cocc_module.builtins_module:
            m.expand_typedef()
    cocc_module.builtins_module.expand_typedef()
    for m in cocc_module.module_map.itervalues():
        if m is not cocc_module.builtins_module:
            m.check_type_for_typedef()

    #统一check_type
    cocc_module.builtins_module.check_type()
    for m in cocc_module.module_map.itervalues():
        if m is not cocc_module.builtins_module:
            m.check_type()

    #检查重载是否有问题
    cocc_module.builtins_module.check_overload()
    for m in cocc_module.module_map.itervalues():
        if m is not cocc_module.builtins_module:
            m.check_overload()

    #主模块main函数检查
    if "main" not in main_module.func_map:
        cocc_common.exit("主模块[%s]没有main函数" % main_module.name)
    main_func_list = main_module.func_map["main"]
    assert main_func_list
    if len(main_func_list) != 1:
        cocc_common.exit("主模块[%s]的main函数禁止重载" % main_module.name)
    main_func = main_func_list[0]
    if main_func.type != cocc_type.INT_TYPE:
        cocc_common.exit("主模块[%s]的main函数返回类型必须为int" % main_module.name)
    if len(main_func.arg_map) != 1:
        cocc_common.exit("主模块[%s]的main函数只能有一个类型为'String[]'的参数" % main_module.name)
    tp = main_func.arg_map.itervalues().next()
    if tp.is_ref or tp.array_dim_count != 1 or tp.to_elem_type() != cocc_type.STR_TYPE:
        cocc_common.exit("主模块[%s]的main函数的参数类型必须为'String[]'" % main_module.name)
    if "public" not in main_func.decr_set:
        cocc_common.exit("主模块[%s]的main函数必须是public的" % main_module.name)

    #检查子类的继承是否合法
    cocc_module.builtins_module.check_sub_class()
    for m in cocc_module.module_map.itervalues():
        if m is not cocc_module.builtins_module:
            m.check_sub_class()

    #todo:其他一些模块元素的检查和进一步预处理

    #正式编译各模块
    cocc_module.builtins_module.compile()
    for m in cocc_module.module_map.itervalues():
        if m is not cocc_module.builtins_module:
            m.compile()

    cocc_output.out_dir = os.path.join(src_dir, main_module.name)
    cocc_output.runtime_dir = os.path.join(os.path.dirname(lib_dir), "runtime")
    cocc_output.output(main_module.name)
Exemplo n.º 12
0
def _show_usage_and_exit():
    cocc_common.exit("使用方法:%s 主模块.coc" % sys.argv[0])