docs: 统一注释风格
This commit is contained in:
parent
493b970d9a
commit
2c4374554e
@ -6,9 +6,10 @@ import java.util.EnumMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 管理不同生命周期阶段与其对应任务的工具类。
|
||||
* 生命周期任务管理器。<br>
|
||||
* 用于管理不同生命周期阶段与其对应 {@link Task},并支持顺序执行所有已注册任务。
|
||||
* <p>
|
||||
* 可为每个 {@link LifecyclePhase} 注册对应的 {@link Task},并按阶段顺序执行所有任务。
|
||||
* 可为每个 {@link LifecyclePhase} 注册对应的 {@link Task},并在构建/部署流程中自动执行。
|
||||
* </p>
|
||||
*
|
||||
* <pre>
|
||||
@ -20,9 +21,7 @@ import java.util.Map;
|
||||
*/
|
||||
public final class LifecycleManager {
|
||||
|
||||
/**
|
||||
* 存储生命周期阶段与对应任务的映射关系。
|
||||
*/
|
||||
/** 生命周期阶段与对应任务的映射关系 */
|
||||
private final Map<LifecyclePhase, Task> tasks = new EnumMap<>(LifecyclePhase.class);
|
||||
|
||||
/**
|
||||
@ -45,11 +44,13 @@ public final class LifecycleManager {
|
||||
|
||||
/**
|
||||
* 按 {@link LifecyclePhase} 声明顺序依次执行所有已注册任务。
|
||||
* <p>
|
||||
* 未注册任务的阶段将被跳过。任务执行前会打印阶段名。
|
||||
* </p>
|
||||
* <ul>
|
||||
* <li>未注册任务的阶段会被自动跳过</li>
|
||||
* <li>每个任务执行前会输出当前阶段名</li>
|
||||
* <li>执行中遇到异常将立即抛出并终止后续执行</li>
|
||||
* </ul>
|
||||
*
|
||||
* @throws Exception 若某个任务执行时抛出异常,将直接抛出并终止后续任务执行
|
||||
* @throws Exception 若某个任务执行时抛出异常,将直接抛出
|
||||
*/
|
||||
public void executeAll() throws Exception {
|
||||
for (LifecyclePhase phase : LifecyclePhase.values()) {
|
||||
|
||||
@ -1,7 +1,10 @@
|
||||
package org.jcnc.snow.pkg.lifecycle;
|
||||
|
||||
/**
|
||||
* 定义了典型软件包生命周期的各个阶段。
|
||||
* 定义典型软件包生命周期的各个阶段枚举。
|
||||
* <p>
|
||||
* 用于区分构建、依赖、发布等不同阶段的任务调度与管理。
|
||||
* </p>
|
||||
*/
|
||||
public enum LifecyclePhase {
|
||||
/** 初始化阶段 */
|
||||
|
||||
@ -6,16 +6,16 @@ import java.util.HashMap;
|
||||
/**
|
||||
* 构建配置对象,封装构建过程中的所有选项。
|
||||
* <p>
|
||||
* 支持基于模板变量(形如{@code @{key}})的选项值替换。
|
||||
* 支持模板变量(形如 <code>@{key}</code>)的值自动替换。
|
||||
* </p>
|
||||
*/
|
||||
public final class BuildConfiguration {
|
||||
|
||||
/** 存储配置项的键值对 */
|
||||
/** 存储所有配置项 */
|
||||
private final Map<String, String> options;
|
||||
|
||||
/**
|
||||
* 私有构造函数,用于初始化配置项。
|
||||
* 私有构造函数,仅供工厂方法调用。
|
||||
*
|
||||
* @param options 配置项键值对
|
||||
*/
|
||||
@ -24,14 +24,15 @@ public final class BuildConfiguration {
|
||||
}
|
||||
|
||||
/**
|
||||
* 基于原始配置项和变量属性创建配置对象。
|
||||
* <p>
|
||||
* 会将原始配置中的所有值中的{@code @{key}}模板,替换为属性props中对应的值。
|
||||
* </p>
|
||||
* 基于原始配置项和属性集创建配置对象。
|
||||
* <ul>
|
||||
* <li>会将所有值中的 <code>@{key}</code> 模板变量,替换为 props 中对应的值</li>
|
||||
* <li>属性未匹配到时保留原模板</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param flat 原始的配置项,值中可包含模板变量(如@{name})
|
||||
* @param props 用于替换模板变量的属性集
|
||||
* @return 构建完成的配置对象
|
||||
* @param flat 原始配置项,值中可包含模板变量
|
||||
* @param props 变量替换用的属性集
|
||||
* @return 处理后生成的配置对象
|
||||
*/
|
||||
public static BuildConfiguration fromFlatMap(Map<String, String> flat, Map<String, String> props) {
|
||||
Map<String, String> resolved = new HashMap<>();
|
||||
@ -46,11 +47,11 @@ public final class BuildConfiguration {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定key对应的配置值。
|
||||
* 获取指定配置项的值。
|
||||
*
|
||||
* @param key 配置项名称
|
||||
* @param def 默认值(若未找到key则返回此值)
|
||||
* @return 配置项对应值,若不存在则返回默认值
|
||||
* @param def 默认值(未找到时返回)
|
||||
* @return 配置项值,若不存在则返回默认值
|
||||
*/
|
||||
public String get(String key, String def) {
|
||||
return options.getOrDefault(key, def);
|
||||
|
||||
@ -5,18 +5,23 @@ import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* group:artifact:version 依赖坐标。
|
||||
* group:artifact:version 依赖坐标对象。
|
||||
* <p>
|
||||
* 支持通过占位符和属性映射进行动态变量替换,可用于构建工具或依赖管理场景。
|
||||
* 支持占位符和属性映射进行动态变量替换,适用于 Snow 语言包管理和源码依赖场景。
|
||||
* </p>
|
||||
*
|
||||
* <pre>
|
||||
* 示例:
|
||||
* 示例用法:
|
||||
* Dependency dep = Dependency.fromString(
|
||||
* "core", "com.example:core:@{version}",
|
||||
* Map.of("version", "1.2.3")
|
||||
* );
|
||||
* </pre>
|
||||
*
|
||||
* @param id 依赖唯一标识
|
||||
* @param group 组织/分组名
|
||||
* @param artifact 构件名
|
||||
* @param version 版本号
|
||||
*/
|
||||
public record Dependency(
|
||||
String id,
|
||||
@ -25,25 +30,23 @@ public record Dependency(
|
||||
String version
|
||||
) {
|
||||
|
||||
/**
|
||||
* 用于匹配 group:artifact:version 格式的正则表达式。
|
||||
*/
|
||||
/** 匹配 group:artifact:version 格式的正则表达式。 */
|
||||
private static final Pattern GAV = Pattern.compile("([^:]+):([^:]+):(.+)");
|
||||
|
||||
/**
|
||||
* 根据字符串坐标和属性映射创建依赖对象。
|
||||
* <p>
|
||||
* 坐标中的占位符如 {@code @{key}} 会用 props 中对应的值替换。
|
||||
* 坐标中的占位符(如 <code>@{key}</code>)会用 props 中对应的值替换。
|
||||
* </p>
|
||||
*
|
||||
* @param id 依赖唯一标识
|
||||
* @param coordinate 依赖坐标字符串,格式为 group:artifact:version,支持变量占位符
|
||||
* @param props 占位符替换的属性映射
|
||||
* @param coordinate 坐标字符串,格式为 group:artifact:version,支持占位符
|
||||
* @param props 占位符替换属性映射
|
||||
* @return 解析后的 Dependency 实例
|
||||
* @throws IllegalArgumentException 如果坐标格式非法
|
||||
* @throws IllegalArgumentException 坐标格式非法时抛出
|
||||
*/
|
||||
public static Dependency fromString(String id, String coordinate, Map<String, String> props) {
|
||||
// 替换 @{prop} 占位符
|
||||
// 替换占位符
|
||||
String resolved = coordinate;
|
||||
for (Map.Entry<String, String> p : props.entrySet()) {
|
||||
resolved = resolved.replace("@{" + p.getKey() + "}", p.getValue());
|
||||
@ -57,23 +60,23 @@ public record Dependency(
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成依赖对应的标准仓库 jar 路径。
|
||||
* 生成依赖对应的源码文件路径。
|
||||
* <p>
|
||||
* 路径格式通常为:groupId/artifactId/version/artifactId-version.jar<br>
|
||||
* 例如:com/example/core/1.2.3/core-1.2.3.jar
|
||||
* 路径格式:groupId/artifactId/version/artifactId.snow
|
||||
* 例如:com/example/core/1.2.3/core.snow
|
||||
* </p>
|
||||
*
|
||||
* @return 仓库 jar 文件的相对路径
|
||||
* @return 仓库源码文件的相对路径
|
||||
*/
|
||||
public String toPath() {
|
||||
String groupPath = group.replace('.', '/');
|
||||
return groupPath + "/" + artifact + "/" + version + "/" + artifact + "-" + version + ".jar";
|
||||
return groupPath + "/" + artifact + "/" + version + "/" + artifact + ".snow";
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回该依赖的 group:artifact:version 字符串表示。
|
||||
*
|
||||
* @return Maven 坐标字符串
|
||||
* @return 坐标字符串
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
|
||||
@ -8,42 +8,41 @@ import java.util.Map;
|
||||
/**
|
||||
* 表示一个软件包/模块的项目信息,包括元数据、属性、仓库、依赖和构建配置等。
|
||||
* <p>
|
||||
* 本类为不可变对象,仅提供getter,无setter。
|
||||
* 支持通过 {@link #fromFlatMap(Map)} 静态工厂方法从扁平Map快速创建。
|
||||
* 本类为不可变对象,仅提供 getter 方法,无 setter。<br>
|
||||
* 支持通过 {@link #fromFlatMap(Map)} 静态工厂方法,从扁平 Map 快速创建实例。
|
||||
* </p>
|
||||
*
|
||||
* <pre>
|
||||
* Map<String,String> map = ...;
|
||||
* Map<String, String> map = ...;
|
||||
* Project project = Project.fromFlatMap(map);
|
||||
* </pre>
|
||||
*/
|
||||
public final class Project {
|
||||
|
||||
/** 组织/分组名(如com.example) */
|
||||
/** 组织/分组名(如 com.example) */
|
||||
private final String group;
|
||||
/** 构件/模块名(如app-core) */
|
||||
/** 构件/模块名(如 app-core) */
|
||||
private final String artifact;
|
||||
/** 项目展示名称 */
|
||||
private final String name;
|
||||
/** 版本号(如1.0.0) */
|
||||
/** 版本号(如 1.0.0) */
|
||||
private final String version;
|
||||
/** 项目描述 */
|
||||
private final String description;
|
||||
/** 许可证标识 */
|
||||
private final String license;
|
||||
/** 项目主页URL */
|
||||
/** 项目主页 URL */
|
||||
private final String homepage;
|
||||
|
||||
/** 额外属性(不影响主字段,可用于模板/占位符) */
|
||||
private final Map<String, String> properties;
|
||||
/** 仓库列表(仓库ID -> 仓库对象) */
|
||||
/** 仓库列表(仓库 ID -> 仓库对象) */
|
||||
private final Map<String, Repository> repositories;
|
||||
/** 依赖列表 */
|
||||
private final List<Dependency> dependencies;
|
||||
/** 构建配置 */
|
||||
private final BuildConfiguration build;
|
||||
|
||||
|
||||
/**
|
||||
* 构造函数(私有),请使用 {@link #fromFlatMap(Map)} 创建实例。
|
||||
*/
|
||||
@ -74,7 +73,7 @@ public final class Project {
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过扁平Map创建 Project 实例。约定key格式如下:
|
||||
* 通过扁平 Map 创建 Project 实例。key 格式约定如下:
|
||||
* <ul>
|
||||
* <li>project.* —— 项目元数据</li>
|
||||
* <li>properties.* —— 额外属性</li>
|
||||
@ -83,12 +82,11 @@ public final class Project {
|
||||
* <li>build.* —— 构建配置</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param map 扁平的配置map
|
||||
* @param map 扁平的配置 map
|
||||
* @return Project 实例
|
||||
*/
|
||||
public static Project fromFlatMap(Map<String, String> map) {
|
||||
|
||||
// 1. simple project metadata
|
||||
// 1. 基本元数据
|
||||
String group = map.getOrDefault("project.group", "unknown");
|
||||
String artifact = map.getOrDefault("project.artifact", "unknown");
|
||||
String name = map.getOrDefault("project.name", artifact);
|
||||
@ -123,14 +121,13 @@ public final class Project {
|
||||
}
|
||||
});
|
||||
|
||||
// 5. build.* simply hand the subtree map
|
||||
// 5. build.*
|
||||
Map<String, String> buildMap = new LinkedHashMap<>();
|
||||
map.forEach((k, v) -> {
|
||||
if (k.startsWith("build.")) {
|
||||
buildMap.put(k.substring("build.".length()), v);
|
||||
}
|
||||
});
|
||||
|
||||
BuildConfiguration buildCfg = BuildConfiguration.fromFlatMap(buildMap, props);
|
||||
|
||||
return new Project(group, artifact, name, version, description, license, homepage, props, repos, deps, buildCfg);
|
||||
@ -161,12 +158,12 @@ public final class Project {
|
||||
return description;
|
||||
}
|
||||
|
||||
/** @return 许可证 */
|
||||
/** @return 许可证标识 */
|
||||
public String getLicense() {
|
||||
return license;
|
||||
}
|
||||
|
||||
/** @return 项目主页URL */
|
||||
/** @return 项目主页 URL */
|
||||
public String getHomepage() {
|
||||
return homepage;
|
||||
}
|
||||
|
||||
@ -3,16 +3,16 @@ package org.jcnc.snow.pkg.model;
|
||||
/**
|
||||
* 表示一个远程仓库的基本信息,通常用于依赖解析和发布。
|
||||
* <p>
|
||||
* 每个仓库由唯一的ID和对应的URL确定。
|
||||
* 每个仓库由唯一的 ID 和对应的 URL 标识。
|
||||
* </p>
|
||||
*
|
||||
* <pre>
|
||||
* 示例:
|
||||
* 示例用法:
|
||||
* Repository repo = new Repository("central", "https://");
|
||||
* </pre>
|
||||
*
|
||||
* @param id 仓库唯一标识
|
||||
* @param url 仓库地址(一般为HTTP(S)链接)
|
||||
* @param url 仓库地址(通常为 HTTP(S) 链接)
|
||||
*/
|
||||
public record Repository(String id, String url) {
|
||||
}
|
||||
|
||||
@ -6,17 +6,27 @@ import java.nio.file.Path;
|
||||
import java.util.Comparator;
|
||||
|
||||
/**
|
||||
* 清理构建输出目录(如 build 和 dist)的任务实现。
|
||||
* 用于清理构建输出目录(如 {@code build} 和 {@code dist})的任务实现类。
|
||||
* <p>
|
||||
* 实现 {@link Task} 接口,通常用于构建流程中的清理阶段。
|
||||
* 实现 {@link Task} 接口,常用于自动化构建流程的清理阶段,负责递归删除指定的构建产物目录。
|
||||
* </p>
|
||||
* <p>
|
||||
* 本类为无状态实现,线程安全。
|
||||
* </p>
|
||||
*
|
||||
* <p><b>示例用法:</b></p>
|
||||
* <pre>{@code
|
||||
* Task clean = new CleanTask();
|
||||
* clean.run();
|
||||
* }</pre>
|
||||
*/
|
||||
public final class CleanTask implements Task {
|
||||
|
||||
/**
|
||||
* 执行清理任务,删除 "build" 和 "dist" 目录及其所有内容。
|
||||
* 执行清理任务,递归删除当前目录下的 {@code build} 和 {@code dist} 目录及其所有内容。
|
||||
* 如果目标目录不存在,则跳过不处理。
|
||||
*
|
||||
* @throws IOException 删除目录过程中出现 IO 错误时抛出
|
||||
* @throws IOException 删除目录或文件过程中发生 IO 错误时抛出
|
||||
*/
|
||||
@Override
|
||||
public void run() throws IOException {
|
||||
@ -27,10 +37,15 @@ public final class CleanTask implements Task {
|
||||
|
||||
/**
|
||||
* 递归删除指定目录及其所有子文件和子目录。
|
||||
* 使用 try-with-resources 自动关闭文件流,避免资源泄漏。
|
||||
* <p>
|
||||
* 若目录不存在,则直接返回。
|
||||
* </p>
|
||||
* <p>
|
||||
* 内部使用 try-with-resources 保证文件流自动关闭,避免资源泄漏。
|
||||
* </p>
|
||||
*
|
||||
* @param dir 需要删除的目录路径
|
||||
* @throws IOException 删除过程中出现 IO 错误时抛出
|
||||
* @throws IOException 删除目录或文件过程中发生 IO 错误时抛出
|
||||
*/
|
||||
private void deleteDir(Path dir) throws IOException {
|
||||
if (Files.notExists(dir)) return;
|
||||
|
||||
@ -25,17 +25,16 @@ import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
|
||||
|
||||
/**
|
||||
* CLI 命令:将 .snow 源文件编译为 VM 字节码(.water 文件)。
|
||||
* CLI 任务:编译 .snow 源文件为 VM 字节码(.water 文件)。
|
||||
* <p>
|
||||
* 支持递归目录、多文件编译,可选编译后立即运行。<br>
|
||||
* 命令参数支持 run、-o、-d 等。
|
||||
* 支持单文件、多文件和目录递归编译,并可在编译后立即运行虚拟机。<br>
|
||||
* 命令行参数支持 run、-o、-d 及直接指定源文件。
|
||||
* </p>
|
||||
*
|
||||
* <pre>
|
||||
* 用法示例:
|
||||
* $ snow compile [run] [-o <name>] [-d <srcDir>] [file1.snow file2.snow …]
|
||||
* $ snow compile [run] [-o <name>] [-d <srcDir>] [file1.snow file2.snow ...]
|
||||
* </pre>
|
||||
*/
|
||||
public final class CompileTask implements Task {
|
||||
@ -44,26 +43,49 @@ public final class CompileTask implements Task {
|
||||
/** 原始命令行参数 */
|
||||
private final String[] args;
|
||||
|
||||
/**
|
||||
* 创建一个编译任务。
|
||||
*
|
||||
* @param project 项目信息对象
|
||||
* @param args 命令行参数数组
|
||||
*/
|
||||
public CompileTask(Project project, String[] args) {
|
||||
this.project = project;
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建一个不带参数的编译任务。
|
||||
*
|
||||
* @param project 项目信息对象
|
||||
*/
|
||||
public CompileTask(Project project) {
|
||||
this(project, new String[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行编译任务。该方法会解析参数并调用 {@link #execute(String[])} 进行实际编译流程。
|
||||
*
|
||||
* @throws Exception 执行过程中出现任意异常时抛出
|
||||
*/
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
// 将任务委托给原始 execute 实现
|
||||
execute(this.args);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* 执行 compile 子命令 */
|
||||
/* --------------------------------------------------------------------- */
|
||||
/**
|
||||
* 编译 .snow 源文件为 VM 字节码,并可选择立即运行。
|
||||
* <ul>
|
||||
* <li>支持参数 run(编译后运行)、-o(输出文件名)、-d(递归目录)、直接指定多个源文件。</li>
|
||||
* <li>输出源代码、AST、IR、最终 VM code,并写出 .water 文件。</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param args 命令行参数数组
|
||||
* @return 0 表示成功,非 0 表示失败
|
||||
* @throws Exception 编译或写入过程中出现异常时抛出
|
||||
*/
|
||||
public int execute(String[] args) throws Exception {
|
||||
/* ---------------- 解析命令行参数 ---------------- */
|
||||
// ---------------- 解析命令行参数 ----------------
|
||||
boolean runAfterCompile = false;
|
||||
String outputName = null;
|
||||
Path dir = null;
|
||||
@ -101,7 +123,7 @@ public final class CompileTask implements Task {
|
||||
}
|
||||
}
|
||||
|
||||
/* --------- 如果指定了目录则递归收集所有 *.snow --------- */
|
||||
// --------- 如果指定了目录则递归收集所有 *.snow ---------
|
||||
if (dir != null) {
|
||||
if (!Files.isDirectory(dir)) {
|
||||
System.err.println("Not a directory: " + dir);
|
||||
@ -119,19 +141,17 @@ public final class CompileTask implements Task {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* 多文件但未指定 -o 且非目录编译 —— 提示必须指定输出名 */
|
||||
// 多文件但未指定 -o 且非目录编译 —— 提示必须指定输出名
|
||||
if (sources.size() > 1 && outputName == null && dir == null) {
|
||||
System.err.println("Please specify output name using -o <name>");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------- */
|
||||
/* 1. 词法 + 语法分析;同时打印源代码 */
|
||||
/* ----------------------------------------------------------------- */
|
||||
// ---------------- 1. 词法/语法分析,并打印源代码 ----------------
|
||||
List<Node> allAst = new ArrayList<>();
|
||||
|
||||
System.out.println("## 编译器输出");
|
||||
System.out.println("### Snow 源代码"); // ========== 新增:二级标题 ==========
|
||||
System.out.println("### Snow 源代码");
|
||||
|
||||
for (Path p : sources) {
|
||||
if (!Files.exists(p)) {
|
||||
@ -141,38 +161,31 @@ public final class CompileTask implements Task {
|
||||
|
||||
String code = Files.readString(p, StandardCharsets.UTF_8);
|
||||
|
||||
// ------- 打印每个文件的源码 -------
|
||||
// 打印源码
|
||||
System.out.println("#### " + p.getFileName());
|
||||
System.out.println(code);
|
||||
// --------------------------------------------------------
|
||||
|
||||
/* 词法 + 语法 */
|
||||
// 词法、语法分析
|
||||
LexerEngine lexer = new LexerEngine(code, p.toString());
|
||||
ParserContext ctx = new ParserContext(lexer.getAllTokens(), p.toString());
|
||||
allAst.addAll(new ParserEngine(ctx).parse());
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------- */
|
||||
/* 2. 语义分析 */
|
||||
/* ----------------------------------------------------------------- */
|
||||
// ---------------- 2. 语义分析 ----------------
|
||||
SemanticAnalyzerRunner.runSemanticAnalysis(allAst, false);
|
||||
|
||||
/* ----------------------------------------------------------------- */
|
||||
/* 3. AST → IR,并把 main 函数调到首位 */
|
||||
/* ----------------------------------------------------------------- */
|
||||
// ---------------- 3. AST → IR,并将 main 函数移动至首位 ----------------
|
||||
IRProgram program = new IRProgramBuilder().buildProgram(allAst);
|
||||
program = reorderForEntry(program);
|
||||
|
||||
/* ---------------- 打印 AST / IR ---------------- */
|
||||
// 打印 AST 和 IR
|
||||
System.out.println("### AST");
|
||||
ASTPrinter.printJson(allAst);
|
||||
|
||||
System.out.println("### IR");
|
||||
System.out.println(program);
|
||||
|
||||
/* ----------------------------------------------------------------- */
|
||||
/* 4. IR → VM 指令 */
|
||||
/* ----------------------------------------------------------------- */
|
||||
// ---------------- 4. IR → VM 指令 ----------------
|
||||
VMProgramBuilder builder = new VMProgramBuilder();
|
||||
List<InstructionGenerator<? extends IRInstruction>> generators =
|
||||
InstructionGeneratorProvider.defaultGenerators();
|
||||
@ -187,16 +200,12 @@ public final class CompileTask implements Task {
|
||||
System.out.println("### VM code");
|
||||
finalCode.forEach(System.out::println);
|
||||
|
||||
/* ----------------------------------------------------------------- */
|
||||
/* 5. 写出 .water 文件 */
|
||||
/* ----------------------------------------------------------------- */
|
||||
// ---------------- 5. 写出 .water 文件 ----------------
|
||||
Path outputFile = deriveOutputPath(sources, outputName, dir);
|
||||
Files.write(outputFile, finalCode, StandardCharsets.UTF_8);
|
||||
System.out.println("Written to " + outputFile.toAbsolutePath());
|
||||
|
||||
/* ----------------------------------------------------------------- */
|
||||
/* 6. 可选:立即运行 VM */
|
||||
/* ----------------------------------------------------------------- */
|
||||
// ---------------- 6. 可选:立即运行 VM ----------------
|
||||
if (runAfterCompile) {
|
||||
System.out.println("\n=== Launching VM ===");
|
||||
VMLauncher.main(new String[]{outputFile.toString()});
|
||||
@ -205,18 +214,19 @@ public final class CompileTask implements Task {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* 辅助方法 */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* 根据输入情况推断 .water 输出文件名:
|
||||
* 推断 .water 输出文件名。
|
||||
* <ul>
|
||||
* <li>若指定 -o,则直接使用</li>
|
||||
* <li>目录编译:取目录名</li>
|
||||
* <li>单文件编译:取文件名去掉 .snow</li>
|
||||
* <li>其他情况兜底为 "program"</li>
|
||||
* <li>如果指定 -o,直接使用该名称。</li>
|
||||
* <li>目录编译时,取目录名。</li>
|
||||
* <li>单文件编译时,取文件名去掉 .snow 后缀。</li>
|
||||
* <li>否则默认 "program"。</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param sources 源文件路径列表
|
||||
* @param outName 输出文件名(如有指定,否则为 null)
|
||||
* @param dir 源码目录(如有指定,否则为 null)
|
||||
* @return 推断出的输出文件路径(.water 文件)
|
||||
*/
|
||||
private static Path deriveOutputPath(List<Path> sources, String outName, Path dir) {
|
||||
String base;
|
||||
@ -234,7 +244,10 @@ public final class CompileTask implements Task {
|
||||
}
|
||||
|
||||
/**
|
||||
* 把 main 函数交换到程序函数列表首位,确保 PC=0 即入口。
|
||||
* 将 main 函数调整至函数列表首位,确保程序入口为 PC=0。
|
||||
*
|
||||
* @param in 原始 IRProgram
|
||||
* @return 调整入口后的 IRProgram
|
||||
*/
|
||||
private static IRProgram reorderForEntry(IRProgram in) {
|
||||
List<IRFunction> ordered = new ArrayList<>(in.functions());
|
||||
|
||||
@ -10,9 +10,10 @@ import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 任务:依据 {@link Project} 元数据创建标准项目目录。
|
||||
* 项目脚手架生成任务。<br>
|
||||
* 根据 {@link Project} 元数据自动创建标准项目目录结构,并生成示例入口文件 <code>src/main.snow</code>。
|
||||
* <p>
|
||||
* 生成内容:
|
||||
* 生成内容包括:
|
||||
* <ul>
|
||||
* <li>src/ —— 源码目录</li>
|
||||
* <li>test/ —— 测试源码目录</li>
|
||||
@ -20,27 +21,44 @@ import java.util.List;
|
||||
* <li>dist/ —— 打包输出目录</li>
|
||||
* <li>src/main.snow —— “Hello, Snow!” 示例入口</li>
|
||||
* </ul>
|
||||
* 如目录或入口文件已存在,则自动跳过,不会覆盖。
|
||||
* </p>
|
||||
*/
|
||||
public final class GenerateTask implements Task {
|
||||
|
||||
/** 项目信息元数据 */
|
||||
private final Project project;
|
||||
|
||||
/**
|
||||
* 创建项目生成任务。
|
||||
*
|
||||
* @param project 项目信息元数据对象
|
||||
*/
|
||||
public GenerateTask(Project project) {
|
||||
this.project = project;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行脚手架生成流程,创建标准目录和入口示例文件。
|
||||
* <ul>
|
||||
* <li>若相关目录不存在则创建</li>
|
||||
* <li>若 <code>src/main.snow</code> 不存在则写入模板</li>
|
||||
* <li>生成过程输出进度信息</li>
|
||||
* </ul>
|
||||
*
|
||||
* @throws IOException 创建目录或写入文件时发生 IO 错误时抛出
|
||||
*/
|
||||
@Override
|
||||
public void run() throws IOException {
|
||||
Path root = Paths.get(".").toAbsolutePath();
|
||||
|
||||
/* -------- 创建目录 -------- */
|
||||
// 创建标准目录
|
||||
List<Path> dirs = List.of(
|
||||
root.resolve("src"),
|
||||
root.resolve("test"),
|
||||
root.resolve("build"),
|
||||
root.resolve("dist")
|
||||
);
|
||||
|
||||
for (Path dir : dirs) {
|
||||
if (Files.notExists(dir)) {
|
||||
Files.createDirectories(dir);
|
||||
@ -48,7 +66,7 @@ public final class GenerateTask implements Task {
|
||||
}
|
||||
}
|
||||
|
||||
/* -------- 创建示例入口文件 -------- */
|
||||
// 创建 src/main.snow 示例入口文件
|
||||
Path mainSnow = root.resolve("src").resolve("main.snow");
|
||||
if (Files.notExists(mainSnow)) {
|
||||
Files.writeString(mainSnow, SnowExampleTemplate.getMainModule());
|
||||
|
||||
@ -9,29 +9,38 @@ import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
/**
|
||||
* 项目打包任务,将编译输出目录(如 build/classes)打包为 .ice 文件。
|
||||
* 项目打包任务,将编译输出目录(如 <code>build/classes</code>)打包为 .ice 文件。
|
||||
* <p>
|
||||
* 实现 {@link Task} 接口,通常用于构建流程中的打包阶段。
|
||||
* 实现 {@link Task} 接口,通常用于构建流程的打包阶段。<br>
|
||||
* 只会打包 build/classes 目录下所有文件,不含其他目录。
|
||||
* </p>
|
||||
* <p>
|
||||
* 输出文件位于 dist 目录,命名为 artifact-version.ice。
|
||||
* </p>
|
||||
*/
|
||||
public final class PackageTask implements Task {
|
||||
|
||||
/** 目标项目 */
|
||||
/** 目标项目元数据 */
|
||||
private final Project project;
|
||||
|
||||
/**
|
||||
* 创建 PackageTask 实例。
|
||||
* 创建打包任务。
|
||||
*
|
||||
* @param project 目标项目
|
||||
* @param project 目标项目元数据
|
||||
*/
|
||||
public PackageTask(Project project) {
|
||||
this.project = project;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行打包任务,将编译输出目录压缩为 artifact-version.ice 文件。
|
||||
* 执行打包任务,将 build/classes 目录下所有文件压缩为 dist/artifact-version.ice。
|
||||
* <ul>
|
||||
* <li>若输出目录 dist 不存在会自动创建</li>
|
||||
* <li>只打包 build/classes 下所有普通文件(保持相对目录结构)</li>
|
||||
* <li>如无 build/classes 则不会生成包</li>
|
||||
* </ul>
|
||||
*
|
||||
* @throws Exception 打包过程中出现 IO 或其他异常时抛出
|
||||
* @throws Exception 打包过程中发生 IO 或其他异常时抛出
|
||||
*/
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
@ -43,15 +52,15 @@ public final class PackageTask implements Task {
|
||||
Path packageFile = distDir.resolve(fileName);
|
||||
|
||||
try (ZipOutputStream zos = new ZipOutputStream(Files.newOutputStream(packageFile))) {
|
||||
// 仅将编译输出目录打包
|
||||
// 仅将 build/classes 目录打包
|
||||
Path classesDir = Path.of("build/classes");
|
||||
if (Files.exists(classesDir)) {
|
||||
// 使用 try-with-resources 正确关闭 Stream<Path>
|
||||
// 遍历所有文件并写入 zip
|
||||
try (Stream<Path> stream = Files.walk(classesDir)) {
|
||||
stream.filter(Files::isRegularFile)
|
||||
.forEach(p -> {
|
||||
try {
|
||||
// 将文件以相对路径加入压缩包
|
||||
// 以 classesDir 为根的相对路径存入 zip
|
||||
zos.putNextEntry(new ZipEntry(classesDir.relativize(p).toString()));
|
||||
Files.copy(p, zos);
|
||||
zos.closeEntry();
|
||||
|
||||
@ -5,25 +5,26 @@ import org.jcnc.snow.pkg.model.Project;
|
||||
/**
|
||||
* 发布项目构件到远程仓库的任务实现。
|
||||
* <p>
|
||||
* 实现 {@link Task} 接口,通常用于构建流程中的发布阶段。目前仅为演示,尚未实现实际上传。
|
||||
* 实现 {@link Task} 接口,通常用于构建流程中的发布阶段。
|
||||
* 当前仅输出发布提示,尚未实现实际上传功能。
|
||||
* </p>
|
||||
*/
|
||||
public final class PublishTask implements Task {
|
||||
|
||||
/** 目标项目 */
|
||||
/** 目标项目元数据 */
|
||||
private final Project project;
|
||||
|
||||
/**
|
||||
* 创建 PublishTask 实例。
|
||||
* 创建发布任务。
|
||||
*
|
||||
* @param project 目标项目
|
||||
* @param project 目标项目元数据
|
||||
*/
|
||||
public PublishTask(Project project) {
|
||||
this.project = project;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行发布任务。当前仅打印发布提示,未实现实际上传逻辑。
|
||||
* 执行发布任务。目前仅打印发布提示信息,未实现实际上传逻辑。
|
||||
*
|
||||
* @throws Exception 预留,未来实现上传逻辑时可能抛出异常
|
||||
*/
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
|
||||
package org.jcnc.snow.pkg.tasks;
|
||||
|
||||
import org.jcnc.snow.vm.VMLauncher;
|
||||
@ -6,26 +5,32 @@ import org.jcnc.snow.vm.VMLauncher;
|
||||
/**
|
||||
* 任务:执行已编译的 VM 字节码文件(.water)。
|
||||
* <p>
|
||||
* 作为 CLI、IDE 插件或其他宿主环境启动虚拟机的统一入口,
|
||||
* 将调用 {@link VMLauncher#main(String[])} 执行。
|
||||
* 作为 CLI、IDE 插件或其他宿主环境启动虚拟机的统一入口,<br>
|
||||
* 通过调用 {@link VMLauncher#main(String[])} 启动 VM 并执行指定程序。
|
||||
* </p>
|
||||
*/
|
||||
public final class RunTask implements Task {
|
||||
|
||||
/** 传递给 VM 的完整参数列表(第一个应为 .water 文件路径) */
|
||||
/**
|
||||
* 传递给虚拟机的完整参数列表(第一个应为 .water 文件路径)
|
||||
*/
|
||||
private final String[] args;
|
||||
|
||||
/**
|
||||
* 创建运行任务。
|
||||
*
|
||||
* @param args VM 参数数组(第一个为程序路径,其后为可选参数)
|
||||
* @param args VM 参数数组(第一个为 .water 程序路径,其后为可选参数)
|
||||
*/
|
||||
public RunTask(String... args) {
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行运行任务,内部委托 {@link VMLauncher#main(String[])}。
|
||||
* 执行运行任务。内部委托 {@link VMLauncher#main(String[])} 启动 VM。
|
||||
* <ul>
|
||||
* <li>如果参数为空则抛出 {@link IllegalArgumentException}</li>
|
||||
* <li>异常由虚拟机本身抛出,直接透出</li>
|
||||
* </ul>
|
||||
*
|
||||
* @throws Exception 虚拟机启动或运行期间抛出的异常
|
||||
*/
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
package org.jcnc.snow.pkg.tasks;
|
||||
|
||||
/**
|
||||
* 构建任务的通用接口,所有具体任务都应实现该接口。
|
||||
* 构建任务的通用接口,所有具体任务(如编译、打包、清理等)都应实现该接口。
|
||||
* <p>
|
||||
* 用于统一生命周期内的任务行为,例如编译、打包、清理等。
|
||||
* 用于统一不同阶段任务的生命周期与执行行为。
|
||||
* </p>
|
||||
*/
|
||||
public interface Task {
|
||||
@ -11,7 +11,7 @@ public interface Task {
|
||||
/**
|
||||
* 执行具体任务的入口方法。
|
||||
*
|
||||
* @throws Exception 任务执行过程中出现的异常
|
||||
* @throws Exception 任务执行过程中出现的任意异常
|
||||
*/
|
||||
void run() throws Exception;
|
||||
}
|
||||
|
||||
@ -1,52 +1,58 @@
|
||||
package org.jcnc.snow.pkg.utils;
|
||||
|
||||
/**
|
||||
* 提供示例 .snow 模块代码模板。
|
||||
* 示例模块模板工具类,提供 main.snow 的标准示例代码字符串。
|
||||
* <p>
|
||||
* 用于项目脚手架生成或帮助用户快速上手 .snow 语言。
|
||||
* </p>
|
||||
*/
|
||||
public final class SnowExampleTemplate {
|
||||
|
||||
/**
|
||||
* 工具类构造方法,禁止实例化。
|
||||
*/
|
||||
private SnowExampleTemplate() {
|
||||
// 工具类不允许实例化
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回 main.snow 示例模块内容。
|
||||
* 获取 main.snow 示例模块的内容字符串。
|
||||
*
|
||||
* @return 示例模块代码字符串
|
||||
* @return main.snow 示例模块的完整代码
|
||||
*/
|
||||
public static String getMainModule() {
|
||||
return """
|
||||
module: Math
|
||||
function: main
|
||||
parameter:
|
||||
return_type: int
|
||||
body:
|
||||
Math.factorial(6)
|
||||
return 0
|
||||
end body
|
||||
end function
|
||||
module: Math
|
||||
function: main
|
||||
parameter:
|
||||
return_type: int
|
||||
body:
|
||||
Math.factorial(6)
|
||||
return 0
|
||||
end body
|
||||
end function
|
||||
|
||||
function: factorial
|
||||
parameter:
|
||||
declare n:int
|
||||
return_type: int
|
||||
body:
|
||||
declare num1:int = 1
|
||||
loop:
|
||||
initializer:
|
||||
declare counter:int = 1
|
||||
condition:
|
||||
counter <= n
|
||||
update:
|
||||
counter = counter + 1
|
||||
body:
|
||||
num1 = num1 * counter
|
||||
end body
|
||||
end loop
|
||||
return num1
|
||||
end body
|
||||
end function
|
||||
end module
|
||||
""";
|
||||
function: factorial
|
||||
parameter:
|
||||
declare n:int
|
||||
return_type: int
|
||||
body:
|
||||
declare num1:int = 1
|
||||
loop:
|
||||
initializer:
|
||||
declare counter:int = 1
|
||||
condition:
|
||||
counter <= n
|
||||
update:
|
||||
counter = counter + 1
|
||||
body:
|
||||
num1 = num1 * counter
|
||||
end body
|
||||
end loop
|
||||
return num1
|
||||
end body
|
||||
end function
|
||||
end module
|
||||
""";
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user