Пример #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) + ".lar"
        if os.path.exists(module_file_path_name):
            return module_file_path_name
    larc_common.exit("找不到模块:%s" % module_name)
Пример #2
0
def _output_util():
    #拷贝runtime中固定的util代码
    util_fix_file_path_name = runtime_dir + "/lar_util.go"
    if not os.path.exists(util_fix_file_path_name):
        larc_common.exit("runtime文件缺失,请检查编译器环境:[%s]" % util_fix_file_path_name)
    f = open("%s/%s.util_fix.go" % (_out_prog_dir, _prog_module_name), "w")
    print >> f, "package %s" % _prog_module_name
    print >> f
    f.write(larc_common.open_src_file(util_fix_file_path_name).read())
    f.close()

    #生成util代码
    with _Code("%s/%s.util.go" % (_out_prog_dir, _prog_module_name)) as code:
        #生成数组相关代码
        for tp in larc_type.array_type_set:
            assert tp.is_array
            arr_type = larc_type.gen_arr_type(tp)
            dim_count = tp.array_dim_count
            while tp.is_array:
                tp = tp.to_elem_type()
            tp_name = _gen_non_array_type_name(tp)
            #数组结构体名和元素类型的code
            arr_tp_name = _gen_arr_tp_name(tp_name, dim_count)
            code += "type %s = %s" % (arr_tp_name, _gen_type_name_code_without_star(arr_type))

        #traceback信息
        with code.new_blk("var lar_util_tb_map = map[lar_util_go_tb]*lar_util_lar_tb"):
            for (go_file_name, go_line_no), tb_info in _tb_map.iteritems():
                if tb_info is None:
                    code += "lar_util_go_tb{file: %s, line: %d}: nil," % (_gen_str_literal(go_file_name), go_line_no)
                else:
                    lar_file_name, lar_line_no, lar_fom_name = tb_info
                    code += ("lar_util_go_tb{file: %s, line: %d}: &lar_util_lar_tb{file: %s, line: %d, fom_name: %s}," %
                             (_gen_str_literal(go_file_name), go_line_no, _gen_str_literal(lar_file_name), lar_line_no,
                              _gen_str_literal(lar_fom_name)))
Пример #3
0
def _get_encoding(src_file, line):
    encoding = "ascii" #默认用ascii编码
    if line.startswith("\xEF\xBB\xBF"):
        #utf-8 bom
        line = line[3 :]
        encoding = "utf8"
        utf8_bom = True
    else:
        utf8_bom = False
    m = re.match(r"#.*coding[=:]\s*([-\w.]+)", line)
    if m is not None:
        #指定了编码
        if utf8_bom:
            larc_common.warning(
                "警告:文件[%s]使用了utf8 bom,忽略指定的coding" % src_file)
        else:
            encoding = m.groups()[0]

    try:
        codecs.lookup(encoding)
    except LookupError:
        larc_common.exit("文件[%s]指定了不支持的编码[%s]" %
                         (src_file, encoding))

    return encoding, line
Пример #4
0
def parse_token_list(src_file):
    f = open(src_file)
    f.seek(0, os.SEEK_END)
    if f.tell() > 100 * 1024 ** 2:
        larc_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
Пример #5
0
def _find_module_file(module_dir_list, module_name):
    #按目录查找,每个目录下优先级:lar、lar_ext
    for module_dir in module_dir_list:
        for ext in (".lar", ".lar_ext"):
            module_file_path_name = os.path.join(module_dir, module_name) + ext
            if os.path.exists(module_file_path_name):
                return module_file_path_name
    larc_common.exit("找不到模块:%s" % module_name)
Пример #6
0
def _find_module_file(module_dir_list, module_name):
    #按目录查找,每个目录下优先级:lar、lar_ext
    for module_dir in module_dir_list:
        for ext in (".lar", ".lar_ext"):
            module_file_path_name = os.path.join(module_dir, module_name) + ext
            if os.path.exists(module_file_path_name):
                return module_file_path_name
    larc_common.exit("找不到模块:%s" % module_name)
Пример #7
0
def _run_prog(args_for_run):
    if platform.system() in ("Darwin", "Linux"):
        pass
    else:
        raise Exception("Bug")
    if os.path.exists(_exe_file):
        os.execv(_exe_file, [_exe_file] + args_for_run)
    else:
        larc_common.exit("找不到可执行文件[%s]" % _exe_file)
Пример #8
0
def _run_prog(args_for_run):
    if platform.system() in ("Darwin", "Linux"):
        pass
    else:
        raise Exception("Bug")
    if os.path.exists(_exe_file):
        os.execv(_exe_file, [_exe_file] + args_for_run)
    else:
        larc_common.exit("找不到可执行文件[%s]" % _exe_file)
Пример #9
0
def main():
    #解析命令行参数
    opt_list, args = getopt.getopt(sys.argv[1:], "", [])

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

    #已编译的模块,模块名映射模块Module对象
    module_map = larc_common.OrderedDict()

    #先编译主模块
    main_file_path_name = os.path.abspath(args[0])
    if main_file_path_name.endswith(".lar"):
        main_module = larc_module.Module(main_file_path_name)
    elif main_file_path_name.endswith(".lar_ext"):
        main_module = larc_module.ExternModule(main_file_path_name)
    else:
        larc_common.exit("非法的主模块文件名[%s]" % main_file_path_name)
    module_map[main_module.name] = main_module

    #模块查找的目录列表
    src_dir = os.path.dirname(main_file_path_name)
    compiler_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
    lib_dir = os.path.join(os.path.dirname(compiler_dir), "lib")
    module_dir_list = [src_dir, lib_dir]

    #编译所有涉及到的模块
    compiling_set = main_module.dep_module_set  #需要编译的模块名集合
    compiling_set |= set(["sys"])  #因为要接收argv,sys模块必须有
    while compiling_set:
        new_compiling_set = set()
        for module_name in compiling_set:
            if module_name in module_map:
                #已编译过
                continue
            module_file_path_name = (_find_module_file(module_dir_list,
                                                       module_name))
            if module_file_path_name.endswith(".lar"):
                module_map[module_name] = m = (
                    larc_module.Module(module_file_path_name))
            elif module_file_path_name.endswith(".lar_ext"):
                module_map[module_name] = m = (
                    larc_module.ExternModule(module_file_path_name))
            else:
                raise Exception("unreachable")
            new_compiling_set |= m.dep_module_set
        compiling_set = new_compiling_set

    prog = larc_prog.Prog(main_module.name, module_map)

    output_lib = larc_output.to_java
    out_dir = src_dir

    output_lib.output(out_dir, prog, lib_dir)
Пример #10
0
def main():
    #解析命令行参数
    opt_list, args = getopt.getopt(sys.argv[1 :], "", [])

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

    #已编译的模块,模块名映射模块Module对象
    module_map = larc_common.OrderedDict()

    #先编译主模块
    main_file_path_name = os.path.abspath(args[0])
    if main_file_path_name.endswith(".lar"):
        main_module = larc_module.Module(main_file_path_name)
    elif main_file_path_name.endswith(".lar_ext"):
        main_module = larc_module.ExternModule(main_file_path_name)
    else:
        larc_common.exit("非法的主模块文件名[%s]" % main_file_path_name)
    module_map[main_module.name] = main_module

    #模块查找的目录列表
    src_dir = os.path.dirname(main_file_path_name)
    compiler_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
    lib_dir = os.path.join(os.path.dirname(compiler_dir), "lib")
    module_dir_list = [src_dir, lib_dir]

    #编译所有涉及到的模块
    compiling_set = main_module.dep_module_set #需要编译的模块名集合
    compiling_set |= set(["sys"]) #因为要接收argv,sys模块必须有
    while compiling_set:
        new_compiling_set = set()
        for module_name in compiling_set:
            if module_name in module_map:
                #已编译过
                continue
            module_file_path_name = (
                _find_module_file(module_dir_list, module_name))
            if module_file_path_name.endswith(".lar"):
                module_map[module_name] = m = (
                    larc_module.Module(module_file_path_name))
            elif module_file_path_name.endswith(".lar_ext"):
                module_map[module_name] = m = (
                    larc_module.ExternModule(module_file_path_name))
            else:
                raise Exception("unreachable")
            new_compiling_set |= m.dep_module_set
        compiling_set = new_compiling_set

    prog = larc_prog.Prog(main_module.name, module_map)

    output_lib = larc_output.to_java
    out_dir = src_dir

    output_lib.output(out_dir, prog, lib_dir)
Пример #11
0
def _output_booter():
    booter_fix_file_path_name = runtime_dir + "/lar_booter.go"
    if not os.path.exists(booter_fix_file_path_name):
        larc_common.exit("runtime文件缺失,请检查编译器环境:[%s]" % booter_fix_file_path_name)
    f = open("%s/%s.booter_fix.go" % (_out_prog_dir, _prog_module_name), "w")
    print >> f, "package %s" % _prog_module_name
    print >> f
    f.write(larc_common.open_src_file(booter_fix_file_path_name).read())
    f.close()

    with _Code("%s/%s.booter.go" % (_out_prog_dir, _prog_module_name)) as code:
        with code.new_blk("func %s()" % _BOOTER_START_PROC_FUNC_NAME):
            code += ("lar_booter_start_prog(%s, %s)" %
                     (_gen_init_mod_func_name(larc_module.module_map[main_module_name]),
                      _gen_func_name(larc_module.module_map[main_module_name].get_main_func())))
Пример #12
0
def _find_module_file(module_path_list, module_name):
    #按模块查找路径逐个目录找
    assert module_path_list
    if module_name == "__builtins":
        mpl = [module_path_list[0]]  #__builtins比较特殊,只从lib_dir找
    else:
        mpl = module_path_list
    for module_dir in mpl:
        module_path = os.path.join(module_dir, *module_name.split("/"))
        if os.path.isdir(module_path):
            return module_path
    t = larc_module.dep_module_token_map.get(module_name)
    if t is None:
        larc_common.exit("找不到模块:%s" % module_name)
    else:
        t.syntax_err("找不到模块:%s" % module_name)
Пример #13
0
def _find_module_file(module_path_list, module_name):
    #按模块查找路径逐个目录找
    assert module_path_list
    if module_name.split("/")[0] in ("__builtins", "__internal", "__array"):
        mpl = [module_path_list[0]] #这几个模块比较特殊,只从lib_dir找
    else:
        mpl = module_path_list
    for i, module_dir in enumerate(mpl):
        module_path = os.path.join(module_dir, *module_name.split("/"))
        if os.path.isdir(module_path):
            return module_path, i == 0
    t = larc_module.dep_module_token_map.get(module_name)
    if t is None:
        larc_common.exit("找不到模块:%s" % module_name)
    else:
        t.syntax_err("找不到模块:%s" % module_name)
Пример #14
0
def _output_booter():
    booter_fix_file_path_name = runtime_dir + "/lar_booter.go"
    if not os.path.exists(booter_fix_file_path_name):
        larc_common.exit("runtime文件缺失,请检查编译器环境:[%s]" %
                         booter_fix_file_path_name)
    f = open("%s/%s.booter_fix.go" % (_out_prog_dir, _prog_module_name), "w")
    print >> f, "package %s" % _prog_module_name
    print >> f
    f.write(larc_common.open_src_file(booter_fix_file_path_name).read())
    f.close()

    with _Code("%s/%s.booter.go" % (_out_prog_dir, _prog_module_name)) as code:
        with code.new_blk("func %s()" % _BOOTER_START_PROC_FUNC_NAME):
            code += ("lar_booter_start_prog(%s, %s)" % (
                _gen_init_mod_func_name(
                    larc_module.module_map[main_module_name]),
                _gen_func_name(
                    larc_module.module_map[main_module_name].get_main_func())))
Пример #15
0
def _output_util():
    #拷贝runtime中固定的util代码
    util_fix_file_path_name = runtime_dir + "/lar_util.go"
    if not os.path.exists(util_fix_file_path_name):
        larc_common.exit("runtime文件缺失,请检查编译器环境:[%s]" % util_fix_file_path_name)
    f = open("%s/%s.util_fix.go" % (_out_prog_dir, _prog_module_name), "w")
    print >> f, "package %s" % _prog_module_name
    print >> f
    f.write(larc_common.open_src_file(util_fix_file_path_name).read())
    f.close()

    #生成util代码
    with _Code("%s/%s.util.go" % (_out_prog_dir, _prog_module_name)) as code:
        #生成数组相关代码
        for tp in larc_type.array_type_set:
            assert tp.is_array
            arr_type = larc_type.gen_arr_type(tp)
            dim_count = tp.array_dim_count
            while tp.is_array:
                tp = tp.to_elem_type()
            tp_name = _gen_non_array_type_name(tp)
            #数组结构体名和元素类型的code
            arr_tp_name = _gen_arr_tp_name(tp_name, dim_count)
            code += "type %s = %s" % (
                arr_tp_name, _gen_type_name_code_without_star(arr_type))

        #traceback信息
        with code.new_blk(
                "var lar_util_tb_map = map[lar_util_go_tb]*lar_util_lar_tb"):
            for (go_file_name, go_line_no), tb_info in _tb_map.iteritems():
                if tb_info is None:
                    code += "lar_util_go_tb{file: %s, line: %d}: nil," % (
                        _gen_str_literal(go_file_name), go_line_no)
                else:
                    lar_file_name, lar_line_no, lar_fom_name = tb_info
                    code += (
                        "lar_util_go_tb{file: %s, line: %d}: &lar_util_lar_tb{file: %s, line: %d, fom_name: %s},"
                        % (_gen_str_literal(go_file_name), go_line_no,
                           _gen_str_literal(lar_file_name), lar_line_no,
                           _gen_str_literal(lar_fom_name)))
Пример #16
0
def _make_prog():
    if platform.system() in ("Darwin", "Linux"):
        try:
            p = subprocess.Popen(["go", "env", "GOPATH"], stdout = subprocess.PIPE)
        except OSError:
            larc_common.exit("无法执行go命令")
        rc = p.wait()
        if rc != 0:
            larc_common.exit("通过go env获取GOPATH失败")
        go_path = p.stdout.read().strip()
        os.environ["GOPATH"] = out_dir + ":" + go_path
        rc = os.system("go build -o %s %s" % (_exe_file, _main_pkg_file))
        if rc != 0:
            larc_common.exit("go build失败")
    else:
        larc_common.exit("不支持在平台'%s'生成可执行程序" % platform.system())
Пример #17
0
def _get_encoding(src_file, line):
    encoding = "ascii"  # 默认用ascii编码
    if line.startswith("\xEF\xBB\xBF"):
        # utf-8 bom
        line = line[3:]
        encoding = "utf8"
        utf8_bom = True
    else:
        utf8_bom = False
    m = re.match(r"#.*coding[=:]\s*([-\w.]+)", line)
    if m is not None:
        # 指定了编码
        if utf8_bom:
            larc_common.warning("警告:文件[%s]使用了utf8 bom,忽略指定的coding" % src_file)
        else:
            encoding = m.groups()[0]

    try:
        codecs.lookup(encoding)
    except LookupError:
        larc_common.exit("文件[%s]指定了不支持的编码[%s]" % (src_file, encoding))

    return encoding, line
Пример #18
0
def _make_prog():
    if platform.system() in ("Darwin", "Linux"):
        try:
            p = subprocess.Popen(["go", "env", "GOPATH"],
                                 stdout=subprocess.PIPE)
        except OSError:
            larc_common.exit("无法执行go命令")
        rc = p.wait()
        if rc != 0:
            larc_common.exit("通过go env获取GOPATH失败")
        go_path = p.stdout.read().strip()
        os.environ["GOPATH"] = out_dir + ":" + go_path
        rc = os.system("go build -o %s %s" % (_exe_file, _main_pkg_file))
        if rc != 0:
            larc_common.exit("go build失败")
    else:
        larc_common.exit("不支持在平台'%s'生成可执行程序" % platform.system())
Пример #19
0
def _output_booter():
    booter_fix_file_path_name = runtime_dir + "/lar_booter.go"
    if not os.path.exists(booter_fix_file_path_name):
        larc_common.exit("runtime文件缺失,请检查编译器环境:[%s]" %
                         booter_fix_file_path_name)
    f = open("%s/%s.booter_fix.go" % (_out_prog_dir, _prog_module_name), "w")
    print >> f, "package %s" % _prog_module_name
    print >> f
    f.write(open(booter_fix_file_path_name).read())
    f.close()

    with _Code("%s/%s.booter.go" % (_out_prog_dir, _prog_module_name)) as code:
        with code.new_blk("import"):
            code += '"os"'
        with code.new_blk("func %s() int" % _BOOTER_START_PROC_FUNC_NAME):
            code += "argv := %s(int64(len(os.Args)))" % (
                _gen_new_arr_func_name(larc_type.STR_TYPE, 1, 1))
            with code.new_blk("for i := 0; i < len(os.Args); i ++"):
                code += "argv.arr[i] = lar_str_from_go_str(os.Args[i])"
            code += ("return lar_booter_start_prog(%s, %s, argv)" % (
                _gen_init_mod_func_name(
                    larc_module.module_map[main_module_name]),
                _gen_func_name(
                    larc_module.module_map[main_module_name].get_main_func())))
Пример #20
0
 def syntax_err(self, msg=""):
     larc_common.exit("%s %s" % (self.pos_desc(), msg))
Пример #21
0
def _show_usage_and_exit():
    larc_common.exit("使用方法:\n"
                     "\t%s --module_path=MODULE_PATH_LIST MAIN_MODULE\n"
                     "\t%s --module_path=MODULE_PATH_LIST --run MAIN_MODULE ARGS" % (sys.argv[0], sys.argv[0]))
Пример #22
0
def main():
    #解析命令行参数
    try:
        opt_list, args = getopt.getopt(sys.argv[1 :], "", ["module_path=", "run"])
    except getopt.GetoptError:
        _show_usage_and_exit()
    opt_map = dict(opt_list)
    if "--module_path" not in opt_map:
        _show_usage_and_exit()
    module_path_list = [os.path.abspath(p) for p in opt_map["--module_path"].split(":") if p]
    need_run = "--run" in opt_map

    if len(args) < 1:
        _show_usage_and_exit()
    main_module_name = args[0]
    args_for_run = args[1 :]
    if not need_run and args_for_run:
        _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")
    module_path_list = [lib_dir] + module_path_list
    larc_module.find_module_file = lambda mn: _find_module_file(module_path_list, mn)

    #larva对标准库第一级模块有一些命名要求,虽然内建模块不会被一般用户修改,但为了稳妥还是检查下,免得开发者不小心弄了个非法名字
    for fn in os.listdir(lib_dir):
        #若为私有模块则忽略掉前缀
        if fn[: 2] == "__":
            fn = fn[2 :]
        #第一级模块名不能有下划线
        if os.path.isdir(os.path.join(lib_dir, fn)) and "_" in fn:
            larc_common.exit("环境检查失败:内建模块[%s]名字含有下划线" % fn)

    #预处理内建模块族
    larc_module.builtins_module = larc_module.module_map["__builtins"] = larc_module.Module("__builtins")
    assert larc_module.builtins_module.get_dep_module_set() == set(["__internal"]) #内建模块只能而且必须导入__internal模块
    internal_module = larc_module.module_map["__internal"] = larc_module.Module("__internal")
    assert not internal_module.get_dep_module_set() #__internal模块不能导入其他模块
    larc_module.array_module = larc_module.module_map["__array"] = larc_module.Module("__array")

    #预处理主模块
    if not (all([larc_token.is_valid_name(p) for p in main_module_name.split("/")]) and main_module_name != "__builtins"):
        larc_common.exit("非法的主模块名[%s]" % main_module_name)
    larc_module.module_map[main_module_name] = main_module = larc_module.Module(main_module_name)

    #预处理所有涉及到的模块
    compiling_set = (larc_module.builtins_module.get_dep_module_set() | larc_module.array_module.get_dep_module_set() |
                     main_module.get_dep_module_set()) #需要预处理的模块名集合
    while compiling_set:
        new_compiling_set = set()
        for module_name in compiling_set:
            if module_name in larc_module.module_map:
                #已预处理过
                continue
            larc_module.module_map[module_name] = m = larc_module.Module(module_name)
            new_compiling_set |= m.get_dep_module_set()
        compiling_set = new_compiling_set
    assert larc_module.module_map.value_at(0) is larc_module.builtins_module

    #检查循环import
    for m in larc_module.module_map.itervalues():
        m.check_cycle_import()

    #模块元素级别的check_type,先对非泛型元素做check,然后对泛型实例采用类似深度优先的方式,直到没有ginst生成
    for m in larc_module.module_map.itervalues():
        m.check_type_for_non_ginst()
    larc_module.check_type_for_ginst()

    #扩展接口中通过usemethod继承的方法
    for m in larc_module.module_map.itervalues():
        m.expand_intf_usemethod()

    #扩展类中通过usemethod继承的方法
    for m in larc_module.module_map.itervalues():
        m.expand_cls_usemethod()

    #主模块main函数检查
    main_module.check_main_func()

    #编译各模块代码,先编译非泛型元素,然后反复编译到没有ginst生成,类似上面的check type过程
    for m in larc_module.module_map.itervalues():
        m.compile_non_ginst()
    while True:
        for m in larc_module.module_map.itervalues():
            if m.compile_ginst():
                #有一个模块刚编译了新的ginst,有可能生成新ginst,重启编译流程
                break
        else:
            #所有ginst都编译完毕
            break

    #输出目标代码
    larc_output.main_module_name = main_module.name
    larc_output.out_dir = main_module.dir + ".lar_out"
    larc_output.runtime_dir = os.path.join(os.path.dirname(lib_dir), "runtime")
    larc_output.output(need_run, args_for_run)
Пример #23
0
def _show_usage_and_exit():
    larc_common.exit("使用方法:%s 主模块.lar" % sys.argv[0])
Пример #24
0
def main():
    #解析命令行参数
    try:
        opt_list, args = getopt.getopt(sys.argv[1:], "",
                                       ["module_path=", "run"])
    except getopt.GetoptError:
        _show_usage_and_exit()
    opt_map = dict(opt_list)
    if "--module_path" not in opt_map:
        _show_usage_and_exit()
    module_path_list = [
        os.path.abspath(p) for p in opt_map["--module_path"].split(":") if p
    ]
    need_run = "--run" in opt_map

    if len(args) < 1:
        _show_usage_and_exit()
    main_module_name = args[0]
    args_for_run = args[1:]
    if not need_run and args_for_run:
        _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")
    module_path_list = [lib_dir] + module_path_list
    larc_module.find_module_file = lambda mn: _find_module_file(
        module_path_list, mn)

    #预处理builtins模块
    larc_module.builtins_module = larc_module.module_map[
        "__builtins"] = larc_module.Module("__builtins")

    #预处理主模块
    if not (all(
        [larc_token.is_valid_name(p) for p in main_module_name.split("/")])
            and main_module_name != "__builtins"):
        larc_common.exit("非法的主模块名[%s]" % main_module_name)
    larc_module.module_map[
        main_module_name] = main_module = larc_module.Module(main_module_name)

    #预处理所有涉及到的模块
    compiling_set = larc_module.builtins_module.get_dep_module_set(
    ) | main_module.get_dep_module_set()  #需要预处理的模块名集合
    while compiling_set:
        new_compiling_set = set()
        for module_name in compiling_set:
            if module_name in larc_module.module_map:
                #已预处理过
                continue
            larc_module.module_map[module_name] = m = larc_module.Module(
                module_name)
            new_compiling_set |= m.get_dep_module_set()
        compiling_set = new_compiling_set
    assert larc_module.module_map.value_at(0) is larc_module.builtins_module

    #模块元素级别的check_type,先对非泛型元素做check,然后对泛型实例采用类似深度优先的方式,直到没有ginst生成
    for m in larc_module.module_map.itervalues():
        m.check_type_for_non_ginst()
    larc_module.check_type_for_ginst()

    #扩展通过usemethod继承的方法
    for m in larc_module.module_map.itervalues():
        m.expand_usemethod()

    #主模块main函数检查
    main_module.check_main_func()

    #编译各模块代码,先编译非泛型元素,然后反复编译到没有ginst生成,类似上面的check type过程
    for m in larc_module.module_map.itervalues():
        m.compile_non_ginst()
    while True:
        for m in larc_module.module_map.itervalues():
            if m.compile_ginst():
                #有一个模块刚编译了新的ginst,有可能生成新ginst,重启编译流程
                break
        else:
            #所有ginst都编译完毕
            break

    #输出目标代码
    larc_output.main_module_name = main_module.name
    larc_output.out_dir = main_module.dir + ".lar_out"
    larc_output.runtime_dir = os.path.join(os.path.dirname(lib_dir), "runtime")
    larc_output.output(need_run, args_for_run)
Пример #25
0
 def peek(self):
     if not self:
         larc_common.exit("语法错误:文件[%s]代码意外结束" % self.src_file)
     return self.l[self.i]
Пример #26
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等模块
    larc_module.module_map["__builtins"] = larc_module.Module(
        os.path.join(lib_dir, "__builtins.lar"))

    #先预处理主模块
    main_file_path_name = os.path.abspath(args[0])
    if not main_file_path_name.endswith(".lar"):
        larc_common.exit("非法的主模块文件名[%s]" % main_file_path_name)
    if not os.path.exists(main_file_path_name):
        larc_common.exit("找不到主模块文件[%s]" % main_file_path_name)
    main_module = larc_module.Module(main_file_path_name)
    larc_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 larc_module.module_map:
                #已预处理过
                continue
            module_file_path_name = _find_module_file(module_dir_list,
                                                      module_name)
            larc_module.module_map[module_name] = m = larc_module.Module(
                module_file_path_name)
            new_compiling_set |= m.dep_module_set
        compiling_set = new_compiling_set

    #主模块main函数检查
    if ("main", 1) not in main_module.func_map:
        larc_common.exit("主模块[%s]没有func main(argv)" % main_module.name)

    #检查子类的继承是否合法
    '''
    for m in larc_module.module_map.itervalues():
        m.check_sub_class()
    '''

    #正式编译各模块
    for m in larc_module.module_map.itervalues():
        m.compile()

    #暂时写死output流程
    output_lib = larc_output.to_go
    output_lib.main_module_name = main_module.name
    output_lib.out_dir = os.path.join(src_dir, main_module.name)
    output_lib.runtime_dir = os.path.join(os.path.dirname(lib_dir), "runtime")
    output_lib.output()
Пример #27
0
 def syntax_err(self, msg = ""):
     larc_common.exit("语法错误:文件[%s]行[%d]列[%d]%s" % (self.src_file, self.line_no, self.pos + 1, msg))
Пример #28
0
 def peek(self, start_idx=0):
     try:
         return self.l[self.i + start_idx]
     except IndexError:
         larc_common.exit("文件[%s]代码意外结束" % self.src_file)
Пример #29
0
 def syntax_err(self, msg = ""):
     larc_common.exit("%s %s" % (self.pos_desc(), msg))
Пример #30
0
def _syntax_err(src_file, line_no, pos, msg):
    larc_common.exit("文件[%s]行[%d]列[%d] %s" % (src_file, line_no, pos + 1, msg))
Пример #31
0
 def peek(self, start_idx = 0):
     try:
         return self.l[self.i + start_idx]
     except IndexError:
         larc_common.exit("文件[%s]代码意外结束" % self.src_file)
Пример #32
0
 def peek(self):
     if not self:
         larc_common.exit("语法错误:文件[%s]代码意外结束" % self.src_file)
     return self.l[self.i]
Пример #33
0
def _syntax_err(src_file, line_no, pos, msg):
    larc_common.exit("文件[%s]行[%d]列[%d] %s" % (src_file, line_no, pos + 1, msg))
Пример #34
0
 def syntax_err(self, msg=""):
     larc_common.exit("语法错误:文件[%s]行[%d]列[%d]%s" % (self.src_file, self.line_no, self.pos + 1, msg))
Пример #35
0
def _show_usage_and_exit():
    larc_common.exit("使用方法:%s 主模块.lar" % sys.argv[0])
Пример #36
0
 def _check_main_func(self):
     main_module = self.module_map[self.main_module_name]
     if ("main", 0) not in main_module.export_func_set:
         larc_common.exit("链接错误:主模块'%s'缺少main函数" % self.main_module_name)
Пример #37
0
def main():
    #定位目录
    THIS_SCRIPT_NAME_SUFFIX = "/compiler/larc.py"
    this_script_name = os.path.realpath(sys.argv[0])
    assert this_script_name.endswith(THIS_SCRIPT_NAME_SUFFIX)
    larva_dir = this_script_name[:-len(THIS_SCRIPT_NAME_SUFFIX)]

    def _show_usage_and_exit():
        print >> sys.stderr, """
Larva编译器

使用方法

    python larc.py OPTIONS MAIN_MODULE_SPEC [ARGS]

各参数说明

    OPTIONS: [-v] [-u] [--recoverable_detecting] [-o OUT_BIN] [--run]

{v}

{u}

{recoverable_detecting}

{o}

        --run
            编译后立即执行

        -o和--run至少要指定一个,若都指定,则先输出为可执行程序然后执行

{MAIN_MODULE_SPEC}

    ARGS

        运行模块时的命令行参数,指定--run选项的时候有效,如未指定--run,则不能指定ARGS
""".format(**eval(open(larva_dir + "/compiler/help_dict").read()))
        sys.exit(1)

    #解析命令行参数
    try:
        opt_list, args = getopt.getopt(sys.argv[1:], "vuo:m:",
                                       ["recoverable_detecting", "run"])
    except getopt.GetoptError:
        _show_usage_and_exit()
    opt_map = dict(opt_list)
    if "-v" in opt_map:
        larc_common.enable_verbose_mode()
    larc_common.verbose_log("开始")
    larc_module.need_update_git = "-u" in opt_map
    if "--recoverable_detecting" in opt_map:
        larc_common.enable_recoverable_detecting()
    out_bin = opt_map.get("-o")
    if out_bin is not None:
        if os.path.exists(out_bin) and not os.path.isfile(out_bin):
            larc_common.exit("[%s]不是一个常规文件" % out_bin)
    need_run = "--run" in opt_map
    if out_bin is None and not need_run:  #至少要指定一种行为
        _show_usage_and_exit()

    main_module_name = opt_map.get("-m")
    if main_module_name is None:
        if len(args) < 1:
            _show_usage_and_exit()
        main_module_path = larc_common.abs_path(args[0])
        if not os.path.isdir(main_module_path):
            larc_common.exit("无效的主模块路径[%s]:不存在或不是目录" % main_module_path)
        args_for_run = args[1:]
    else:
        main_module_path = None
        args_for_run = args[:]
    if not need_run and args_for_run:
        _show_usage_and_exit()

    #获取标准库、用户库和临时输出的目录,并做检查
    compiler_dir = larva_dir + "/compiler"
    std_lib_dir = larva_dir + "/lib"
    assert os.path.isdir(std_lib_dir)
    usr_lib_dir_original = os.getenv("LARVA_USR_LIB_DIR", "~/larva")
    usr_lib_dir = os.path.realpath(larc_common.abs_path(usr_lib_dir_original))
    if not os.path.isdir(usr_lib_dir):
        larc_common.exit("无效的用户库路径:[%s]不存在或不是一个目录" % usr_lib_dir_original)
    tmp_dir_original = os.getenv("LARVA_TMP_DIR", "~/tmp")
    tmp_dir = os.path.realpath(larc_common.abs_path(tmp_dir_original))
    if not os.path.isdir(tmp_dir):
        larc_common.exit("无效的临时工作目录:[%s]不存在或不是一个目录" % tmp_dir_original)

    for (dn_1, d_1), (dn_2, d_2) in itertools.combinations({
            "标准库目录": std_lib_dir,
            "用户库目录": usr_lib_dir,
            "临时工作目录": tmp_dir,
    }.iteritems(), 2):
        if d_1 == d_2:
            larc_common.exit("环境检查失败:%s[%s]和%s[%s]是相同目录" %
                             (dn_1, d_1, dn_2, d_2))
        if d_1.startswith(d_2 + "/") or d_2.startswith(d_1 + "/"):
            larc_common.exit("环境检查失败:%s[%s]和%s[%s]存在包含关系" %
                             (dn_1, d_1, dn_2, d_2))

    #建立临时输出目录
    tmp_out_dir = tmp_dir + "/.larva_tmp_out"
    if not os.path.isdir(tmp_out_dir):
        try:
            os.makedirs(tmp_out_dir)
        except OSError:
            larc_common.exit("创建临时输出目录[%s]失败" % tmp_out_dir)

    if std_lib_dir.startswith(usr_lib_dir) or usr_lib_dir.startswith(
            std_lib_dir):
        larc_common.exit("环境检查失败:标准库和用户库路径存在包含关系:[%s] & [%s]" %
                         (std_lib_dir, usr_lib_dir))

    #larva对标准库第一级模块有一些命名要求,虽然内建模块不会被一般用户修改,但为了稳妥还是检查下,免得开发者不小心弄了个非法名字
    first_level_std_module_set = set()
    for fn in os.listdir(std_lib_dir):
        if os.path.isdir(std_lib_dir + "/" + fn):
            if not larc_token.is_valid_name(fn):
                larc_common.exit("环境检查失败:标准库模块[%s]名字不是合法的标识符" % fn)
            #第一级模块名不能有除了私有模块前导之外的下划线
            if fn.count("_") != (2 if fn.startswith("__") else 0):
                larc_common.exit("环境检查失败:标准库模块[%s]名字含有非法的下划线" % fn)
            first_level_std_module_set.add(fn)

    #检查一下几个特殊的标准库模块,必须有
    for mn in larc_common.STD_LIB_INTERNAL_MODULES:
        if mn not in first_level_std_module_set:
            larc_common.exit("环境检查失败:标准库模块[%s]缺失" % mn)

    #对于用户库中的模块,如果不是git地址,则也要满足合法标识符条件,且不能和标准库的冲突
    for fn in os.listdir(usr_lib_dir):
        if os.path.isdir(usr_lib_dir + "/" + fn):
            if "." not in fn:
                if not larc_token.is_valid_name(fn):
                    larc_common.exit("环境检查失败:用户库模块[%s]名字不是合法的标识符" % fn)
                if fn in first_level_std_module_set:
                    larc_common.exit("环境检查失败:用户库模块[%s]和标准库同名模块冲突" % fn)

    #校验通过,设置到module模块中
    larc_module.std_lib_dir = std_lib_dir
    larc_module.usr_lib_dir = usr_lib_dir

    def fix_git_module_name(mn):
        parts = mn.split("/")
        if len(parts) > 3 and "." in parts[0]:
            git_repo = "/".join(parts[:3])
            mn_of_repo = "/".join(parts[3:])
            if larc_module.is_valid_git_repo(git_repo):
                mn = '"%s"/%s' % (git_repo, mn_of_repo)
        return mn

    if main_module_path is not None:
        #处理main_module_path,提取main_module_name
        if main_module_path.startswith(std_lib_dir + "/"):
            main_module_name = main_module_path[len(std_lib_dir) + 1:]
            if main_module_name in larc_common.STD_LIB_INTERNAL_MODULES:
                larc_common.exit("不能以'%s'作为主模块" % main_module_name)
        elif main_module_path.startswith(usr_lib_dir + "/"):
            main_module_name = fix_git_module_name(
                main_module_path[len(usr_lib_dir) + 1:])
        else:
            larc_common.exit("主模块路径不存在于标准库或用户库[%s]" % main_module_path)
    else:
        #如果module_name是不带引号的git路径,则像上面一样修正一下
        main_module_name = fix_git_module_name(main_module_name)

    #检查
    if not larc_module.is_valid_module_name(main_module_name):
        larc_common.exit("非法的主模块全名'%s'" % main_module_name)
    git_repo, mnpl = larc_module.split_module_name(main_module_name)
    if any([mnp.startswith("__") for mnp in mnpl]):
        larc_common.exit("不能使用私有模块作为主模块'%s'" % main_module_name)

    larc_common.verbose_log("初始化完毕,主模块'%s'" % main_module_name)

    #预处理内建模块族
    larc_module.builtins_module = larc_module.module_map[
        "__builtins"] = larc_module.Module("__builtins")
    assert larc_module.builtins_module.get_dep_module_set() == set(
        ["__internal"])  #内建模块只能而且必须导入__internal模块
    internal_module = larc_module.module_map[
        "__internal"] = larc_module.Module("__internal")
    assert not internal_module.get_dep_module_set()  #__internal模块不能导入其他模块
    larc_module.array_module = larc_module.module_map[
        "__array"] = larc_module.Module("__array")
    larc_module.module_map["__runtime"] = larc_module.Module("__runtime")
    larc_module.module_map["__default"] = larc_module.Module("__default")

    #预处理主模块
    larc_module.module_map[
        main_module_name] = main_module = larc_module.Module(main_module_name)
    module_tmp_out_dir = tmp_out_dir + "/" + main_module_name.replace('"', "")

    larc_common.verbose_log("内建模块和主模块预处理完毕")

    #预处理所有涉及到的模块
    larc_common.inc_verbose_indent()
    compiling_set = set()  #需要预处理的模块全名集合
    for m in larc_module.module_map.itervalues():
        compiling_set |= m.get_dep_module_set()
    while compiling_set:
        new_compiling_set = set()
        for module_name in compiling_set:
            if module_name in larc_module.module_map:
                #已预处理过
                continue
            larc_module.module_map[module_name] = m = larc_module.Module(
                module_name)
            new_compiling_set |= m.get_dep_module_set()
        compiling_set = new_compiling_set
    assert larc_module.module_map.value_at(0) is larc_module.builtins_module
    larc_common.dec_verbose_indent()

    larc_common.verbose_log("所有模块预处理完毕")

    compile_start_time = time.time()

    #检查循环import
    for m in larc_module.module_map.itervalues():
        m.check_cycle_import()

    #模块元素级别的check_type,先对非泛型元素做check,然后对泛型实例采用类似深度优先的方式,直到没有ginst生成
    for m in larc_module.module_map.itervalues():
        m.check_type_for_non_ginst()
    larc_module.check_type_for_ginst()

    #扩展接口中通过usemethod继承的方法
    for m in larc_module.module_map.itervalues():
        m.expand_intf_usemethod()

    #扩展类中通过usemethod继承的方法
    for m in larc_module.module_map.itervalues():
        m.expand_cls_usemethod()

    #初始化函数的合法性检查
    for m in larc_module.module_map.itervalues():
        m.check_init_func()

    #主模块main函数检查
    main_module.check_main_func()

    #编译各模块代码,先编译非泛型元素,然后反复编译到没有ginst生成,类似上面的check type过程
    for m in larc_module.module_map.itervalues():
        m.compile_non_ginst()
    while True:
        for m in larc_module.module_map.itervalues():
            if m.compile_ginst():
                #有一个模块刚编译了新的ginst,有可能生成新ginst,重启编译流程
                break
        else:
            #所有ginst都编译完毕
            break

    larc_common.verbose_log("语法编译完毕,耗时%.2f秒" %
                            (time.time() - compile_start_time))

    #输出目标代码
    larc_output.main_module_name = main_module.name
    larc_output.out_dir = module_tmp_out_dir
    larc_output.output(out_bin, need_run, args_for_run)
Пример #38
0
def _output_util():
    #拷贝runtime中固定的util代码
    util_fix_file_path_name = runtime_dir + "/lar_util.go"
    if not os.path.exists(util_fix_file_path_name):
        larc_common.exit("runtime文件缺失,请检查编译器环境:[%s]" % util_fix_file_path_name)
    f = open("%s/%s.util_fix.go" % (_out_prog_dir, _prog_module_name), "w")
    print >> f, "package %s" % _prog_module_name
    print >> f
    f.write(open(util_fix_file_path_name).read())
    f.close()

    #生成util代码
    with _Code("%s/%s.util.go" % (_out_prog_dir, _prog_module_name)) as code:
        with code.new_blk("import"):
            code += '"fmt"'
            code += '"strings"'
        #生成数组相关代码
        for tp in larc_type.array_type_set:
            assert tp.is_array
            dim_count = tp.array_dim_count
            while tp.is_array:
                tp = tp.to_elem_type()
            tp_name = _gen_non_array_type_name(tp)
            #数组结构体名和元素类型的code
            arr_tp_name = _gen_arr_tp_name(tp_name, dim_count)
            if dim_count == 1:
                elem_tp_name_code = _gen_tp_name_code_from_tp_name(tp_name)
            else:
                elem_tp_name_code = _gen_arr_tp_name_code(
                    tp_name, dim_count - 1)
            #数组结构体定义:元素的slice
            with code.new_blk("type %s struct" % arr_tp_name):
                code += "arr []%s" % elem_tp_name_code
            #数组的方法
            with code.new_blk("func (la *%s) lar_method_size() int64" %
                              arr_tp_name):
                code += "return int64(len(la.arr))"
            with code.new_blk("func (la *%s) lar_method_cap() int64" %
                              arr_tp_name):
                code += "return int64(cap(la.arr))"
            with code.new_blk(
                    "func (la *%s) lar_method_repr() %s" %
                (arr_tp_name, _gen_type_name_code(larc_type.STR_TYPE))):
                code += 'sl := []string{%s, "", ">"}' % _gen_str_literal(
                    "<%s " % (str(tp) + "[]" * dim_count))
                code += "sl[1] = la.sub_arr_repr()"
                code += 'return lar_str_from_go_str(strings.Join(sl, ""))'
            with code.new_blk("func (la *%s) sub_arr_repr() string" %
                              arr_tp_name):
                if tp == larc_type.CHAR_TYPE and dim_count == 1:
                    code += 'return fmt.Sprintf("%q", string(la.arr))'
                else:
                    code += "sl := make([]string, 0, len(la.arr) + 2)"
                    code += 'sl = append(sl, "[")'
                    with code.new_blk("for i, elem := range la.arr"):
                        if dim_count == 1:
                            elem_repr_code = "lar_go_func_any_repr_to_go_str(elem)"
                        else:
                            assert dim_count > 1
                            elem_repr_code = "elem.sub_arr_repr()"
                        with code.new_blk("if i == 0"):
                            code += "sl = append(sl, %s)" % elem_repr_code
                        with code.new_blk("else"):
                            code += 'sl = append(sl, ", " + %s)' % elem_repr_code
                    code += 'sl = append(sl, "]")'
                    code += 'return strings.Join(sl, "")'
            with code.new_blk("func (la *%s) lar_method_get(idx int64) %s" %
                              (arr_tp_name, elem_tp_name_code)):
                code += "return la.arr[idx]"
            with code.new_blk(
                    "func (la *%s) lar_method_set(idx int64, elem %s)" %
                (arr_tp_name, elem_tp_name_code)):
                code += "la.arr[idx] = elem"
            with code.new_blk(
                    "func (la *%s) lar_method_iter() *lar_gcls_inst_10___builtins_9_ArrayIter_1_%s"
                    % (arr_tp_name, elem_tp_name_code.lstrip("*"))):
                code += "return lar_new_obj_lar_gcls_inst_10___builtins_9_ArrayIter_1_%s(la, 0)" % elem_tp_name_code.lstrip(
                    "*")
            with code.new_blk(
                    "func (la *%s) lar_method_copy_from(src *%s) int64" %
                (arr_tp_name, arr_tp_name)):
                code += "return int64(copy(la.arr, src.arr))"
            #输出数组的反射接口
            code += "var lar_reflect_type_name_%s = lar_str_from_go_str(%s)" % (
                arr_tp_name, _gen_str_literal(str(tp) + "[]" * dim_count))
            with code.new_blk(
                    "func (la *%s) lar_reflect_type_name() %s" %
                (arr_tp_name, _gen_type_name_code(larc_type.STR_TYPE))):
                code += "return lar_reflect_type_name_%s" % arr_tp_name
            #new数组的函数
            for new_dim_count in xrange(1, dim_count + 1):
                new_arr_func_name = _gen_new_arr_func_name_by_tp_name(
                    tp_name, dim_count, new_dim_count)
                arg_code = ", ".join(
                    ["d%d_size" % i for i in xrange(new_dim_count)]) + " int64"
                if new_dim_count == 1:
                    if elem_tp_name_code[
                            0] == "*" or elem_tp_name_code.startswith(
                                "lar_intf") or elem_tp_name_code.startswith(
                                    "lar_gintf"):
                        elem_code = "nil"
                    elif elem_tp_name_code == "bool":
                        elem_code = "false"
                    else:
                        elem_code = "0"
                else:
                    assert new_dim_count > 1
                    elem_code = "%s(%s)" % (_gen_new_arr_func_name_by_tp_name(
                        tp_name, dim_count - 1, new_dim_count - 1), ", ".join(
                            ["d%d_size" % i
                             for i in xrange(1, new_dim_count)]))
                with code.new_blk("func %s(%s) *%s" %
                                  (new_arr_func_name, arg_code, arr_tp_name)):
                    code += "la := &%s{arr: make([]%s, d0_size)}" % (
                        arr_tp_name, elem_tp_name_code)
                    with code.new_blk("for i := int64(0); i < d0_size; i ++"):
                        code += "la.arr[i] = %s" % elem_code
                    code += "return la"

        #traceback信息
        with code.new_blk(
                "var lar_util_tb_map = map[lar_util_go_tb]*lar_util_lar_tb"):
            for (go_file_name, go_line_no), tb_info in _tb_map.iteritems():
                if tb_info is None:
                    code += "lar_util_go_tb{file: %s, line: %d}: nil," % (
                        _gen_str_literal(go_file_name), go_line_no)
                else:
                    lar_file_name, lar_line_no, lar_fom_name = tb_info
                    code += (
                        "lar_util_go_tb{file: %s, line: %d}: &lar_util_lar_tb{file: %s, line: %d, fom_name: %s},"
                        % (_gen_str_literal(go_file_name), go_line_no,
                           _gen_str_literal(lar_file_name), lar_line_no,
                           _gen_str_literal(lar_fom_name)))

        #native文件名映射信息
        with code.new_blk(
                "var lar_util_native_file_name_map = map[string]string"):
            for out_nfn, in_nfn in _native_file_name_map.iteritems():
                code += "%s: %s," % (_gen_str_literal(out_nfn),
                                     _gen_str_literal(in_nfn))
Пример #39
0
def _show_usage_and_exit():
    larc_common.exit(
        "使用方法:\n"
        "\t%s --module_path=MODULE_PATH_LIST MAIN_MODULE\n"
        "\t%s --module_path=MODULE_PATH_LIST --run MAIN_MODULE ARGS" %
        (sys.argv[0], sys.argv[0]))