GET STARTED

HP 上手教程HP Tutorial

如果你会 Python 或 C,十分钟就能写出第一段 HP。从安装到所有权,循序渐进。If you know Python or C, you'll write HP in ten minutes. From install to ownership, step by step.

安装与编译Install & Compile

下载 hpc(内置 LLVM 后端与 LLD 链接器)并加入 PATH。HP 没有运行时:hpc 默认 -O2,直接产出原生可执行文件。Download hpc (bundles the LLVM backend and LLD) and add it to PATH. HP has no runtime: hpc defaults to -O2 and emits a native executable.

terminal
hpc hello.hp            # 默认 -O2,生成 hello.hp 同目录的 hello.exe
hpc -O3 --lto hello.hp  # 极致速度 + 跨模块链接期优化
./hello.exe

Hello, WorldHello, World

程序从 main() 开始执行。用 module { "<std.io>" } 解锁内置 I/O(类比 C 的 #include <stdio.h>),随后用 std.io.print 输出。# 是注释;缩进与大括号都可划分代码块,两者等价。Execution starts at main(). module { "<std.io>" } unlocks built-in I/O (like C's #include <stdio.h>), then std.io.print outputs. # comments the line; indentation or braces define blocks — both are equivalent.

hello.hp
module { "<std.io>" }

# 单行注释
## 多行注释
这里随便写,用 ## 结束
##

fn main() {
    std.io.print("Hello, HP!")
}

变量、类型与运算Variables, Types & Math

num 是编译期数值别名,整数解析为原生字长,浮点解析为 f64;要精确宽度就用 i8i64f32f64。字符串用 "'num is a compile-time numeric alias (int → native word, float → f64); use i32, f64… for exact widths. Strings use " or '.

types.hp
module { "<std.io>" }

a = 10            # int(底层 i64)
pi: f64 = 3.1415  # 显式类型注解
name = "HP"

c = a + pi * 2    # 混合运算,编译期提升为 float
msg = f"你好,{name}! sum = {c}"
std.io.print(msg)

to_int: i32 = i32(pi)   # 显式截断转换
is_ready: bool = true   # bool 真假
std.io.print(to_int)

零运行时:f-string 在编译期展开为字符串拼接,运行时零格式化开销;int→float 扩宽自动进行,float→int 必须显式转换。Zero-runtime: f-strings expand to string concatenation at compile time — zero formatting cost; int→float widens automatically, float→int must be explicit.

控制流Control Flow

if / elif / elseforwhile 和 Python 类似;break / continue 语义一致。遍历已知类型时编译器会特化成原生循环,性能与手写 C 相当。if / elif / else, for and while feel like Python; break / continue work the same. Iterating known types specializes to native loops — C-level performance.

flow.hp
module { "<std.io>" }

for i in range(1, 7):
    if i % 2 == 0:
        std.io.print(f"{i} 是偶数")
    else:
        std.io.print(f"{i} 是奇数")

n = 0
while n < 3:
    std.io.print(n)
    n += 1

函数、默认参数与递归Functions, Defaults & Recursion

fn 定义函数;返回类型用 ->: 皆可,两者等价。默认参数必须是编译期常量。尾递归会自动编译为 goto,零栈帧增长。Define functions with fn; the return type accepts -> or :. Default args must be compile-time constants. Tail recursion compiles to goto — no stack growth.

fn.hp
module { "<std.io>" }

fn greet(name: str, prefix: str = "Hi") -> str {
    return f"{prefix}, {name}"
}

fn factorial(n) {
    if n <= 1:
        return 1
    return n * factorial(n - 1)
}

std.io.print(greet("HP"))
std.io.print(factorial(5))   # 120

匿名函数与闭包Closures

匿名函数用 fn(参数){...} 直接作表达式,是 map / filter 与高阶函数的绝配。它们能捕获外部变量形成闭包。Use fn(参数){...} as an inline expression — ideal for map / filter and higher-order functions. They can capture outer variables to form closures.

closure.hp
module { "<std.io>" }

double = fn(x) { return x * 2 }
std.io.print(double(21))        # 42

fn apply(func, value) { return func(value) }
std.io.print(apply(fn(x) { return x * 3 }, 10))   # 30

fn make_adder(base) {
    return fn(x) { return x + base }  # 闭包捕获 base
}
add10 = make_adder(10)
std.io.print(add10(5))          # 15

结构体与实现Structs & impl

struct 定义值类型,impl 添加方法。字段按关键字参数实例化,编译器自动重排消除 padding,零开销访问。Define value types with struct and attach methods with impl. Instantiate by keyword, and the compiler reorders fields to kill padding — zero-cost access.

oop.hp
module { "<std.io>" }

struct Vec2 { x: num; y: num }

impl Vec2 {
    fn len(self) -> num {
        return (self.x ** 2 + self.y ** 2) ** 0.5
    }
    fn origin() -> Vec2 {   # 关联函数
        return Vec2 { x: 0, y: 0 }
    }
}

v = Vec2 { x: 3, y: 4 }
std.io.print(v.len())          # 5.0
o = Vec2::origin()      # (0, 0)

枚举与 matchEnums & match

枚举是带标签的联合体,可携带数据(如 Option::Some(v))。match 被编译为跳转表或 if-else 链,必须覆盖所有变体。Enums are tagged unions that can carry data (e.g. Option::Some(v)). match compiles to a jump table or if-else chain and must cover every variant.

enum.hp
module { "<std.io>" }

enum Status { Ok, Warn, Err }

fn label(s: Status) -> str {
    return match s {
        Status::Ok   => "成功"
        Status::Warn => "警告"
        Status::Err  => "错误"
    }
}

enum Shape { Circle(num); Rect(num, num) }
area = match Shape::Circle(10) {
    Shape::Circle(r)    => 3.14159 * r * r
    Shape::Rect(w, h)   => w * h
}
std.io.print(area)
std.io.print(label(Status::Err))   # "错误"

switch 范围匹配switch & Ranges

switch 对整数或枚举分支,支持 case 90..=100 范围、多值 case 6, 7default。分支隐式 break,不会 fall-through(除非显式 fallthrough)。switch branches on ints or enums with range (case 90..=100), multi-value (case 6, 7) and default. Implicit break — no fall-through unless fallthrough is explicit.

switch.hp
fn grade(score: u32) -> str {
    switch (score) {
        case 90..=100: "优秀"
        case 80..89:   "良好"
        case 60..79:   "及格"
        default:       "不及格"
    }
}

fn is_weekend(day: u8) -> bool {
    switch (day) {
        case 6, 7: true
        default:   false
    }
}

推导式与管道Comprehensions & Pipeline

map / filter 返回惰性迭代器,配合 list() 物化;管道操作符 |> 让数据从左到右流动,编译期展开为嵌套调用,纯语法糖。推导式直接展开为高效循环。map / filter return lazy iterators, realized with list(); the |> pipe flows data left-to-right and is pure syntax at compile time. Comprehensions lower to tight loops.

comp.hp
module { "<std.io>" }

nums = [1, 2, 3, 4, 5, 6]

doubled = nums
    |> map(fn(x) { return x * 2 })
    |> filter(fn(x) { return x > 5 })
std.io.print(list(doubled))          # [6, 8, 10, 12](map 后 filter)

squares = [x * x for x in nums if x % 2 == 0]
std.io.print(squares)                # [4, 16, 36]

pairs = {k: v for k, v in zip(["a", "b"], [1, 2])}
std.io.print(pairs)

惰性:map/filter 按需逐个求值,不预先分配结果数组;配合 zipenumerate 可组合成高效数据管线。Lazy: map/filter evaluate on demand without preallocating; combine with zip, enumerate to build efficient pipelines.

所有权:移动与借用Ownership: Move & Borrow

堆类型赋值默认不拷贝——用 move 显式转移所有权,或用 & / &mut 借用。借用规则在编译期检查,运行时零开销。Heap types aren't copied on assignment — use move to transfer ownership explicitly, or & / &mut to borrow. Rules are checked at compile time with zero runtime cost.

own.hp
module { "<std.io>" }

data = [1, 2, 3]
b = &data          # 不可变借用,data 仍可用
std.io.print(b[0])

owned = move data  # 转移所有权,此后 data 失效
std.io.print(owned[2])

fn read_only(x: &list[num]) { std.io.print(x.len()) }
fn modify(x: &mut list[num]) { x.append(6) }

零运行时:所有权转移与借用检查完全在编译期完成,运行时没有引用计数或 GC——只要不显式使用 weak[T] 打破循环。Zero-runtime: ownership and borrow-checking happen entirely at compile time — no refcount or GC unless you opt into weak[T].

零运行时特性一览Zero-Runtime Highlights

HP 的语言核心遵循「任何运行时开销都必须显式可见」。这些特性全部编译期完成:HP's core is "every runtime cost must be an explicit choice." All of these happen at compile time:

meta.hp
module { "<std.io>" }

const fn square(n) { return n * n }
std.io.print(square(9))                    # 编译期求值

# 编译期类型断言与分支
vec = [1, 2, 3]
@compile_time_assert(@TypeOf(vec) == list[num])

macro check(n) { return n > 0 }   # 宏:替代 eval 的编译期代码生成
defer cleanup()                   # RAII 语法糖,离开作用域自动执行

# -O3 下自动向量化、inline、兄弟/冷热路径切分、LTO、PGO 一应俱全

想看真实代码?Want real code?

示例库收录了结构体、枚举、match、switch、接口、宏、defer、命名空间、FFI 与并发等真实 .hp 文件。The example corpus includes struct, enum, match, switch, interface, macro, defer, namespace, FFI and concurrency .hp files.