示例#1
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)
示例#2
0
文件: larc.py 项目: fibphp/larva-lang
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)
示例#3
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()
示例#4
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)
示例#5
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)