6 个版本
0.3.4 | 2023年3月7日 |
---|---|
0.3.3 | 2023年2月27日 |
0.3.0 | 2023年1月8日 |
0.2.1 | 2022年10月12日 |
248 在 编程语言 中
450KB
18K SLoC
包含 (WOFF 字体, 28KB) iosevka-fixed-regular-stripped.woff, (WOFF 字体, 28KB) iosevka-fixed-bold-stripped.woff
Penne 是一种 怪异编程语言,想象一个世界,在这个世界中,goto 语句没有被排斥,反而成为控制流的主要方法,超过了 for 循环和 switch 语句,最终消除了对 RAII 和面向对象编程的发明需求。通过将现代感应用于goto语句的使用,而不是完全摒弃它,Penne 旨在带来面向意大利面的编程的复兴。
快速尝鲜
Penne 的一般美学灵感来自现代编程语言(特别是 Rust),唯一的例外是标签和goto语句,这些(至少在语法上)来自C语言,以及loop语句。
// Calculate the number of Collatz steps needed to reach 1.
// The Collatz conjecture states that this function always terminates.
fn determine_collatz_number(start: i32) -> i32
{
var x = start;
var steps = 0;
{
if x == 1
goto return;
do_collatz_step(&x);
steps = steps + 1;
loop;
}
return: steps
}
// If x is even, divide it by 2. Otherwise calculate 3 * x + 1.
// Do this without division or modulo operators (for demonstrative purposes).
fn do_collatz_step(x: &i32)
{
var y = x;
{
if y == 0
{
if y + y == x
{
x = y;
goto end;
}
y = y + 1;
loop;
}
else if y == 1
{
x = 3 * x + 1;
goto end;
}
y = y - 2;
loop;
}
end:
}
用法
编译器使用LLVM作为其后端。它需要安装LLVM版本6.0或更高版本。
# Install it (requires Rust 1.60.0 or newer):
cargo install penne
# Compile a source file:
penne examples/addition.pn
# Or run it directly (using lli):
penne run examples/addition.pn
# Output: 10
有适用于Ubuntu 20.04的预编译的二进制文件。
语言特性
Penne 更多独特语言特性的简要概述
作用域goto语句
在 Penne 中,goto 是一个局部单向前跳。这是通过给标签赋予反向作用域来实现的:类似于变量在声明之前不能被引用,标签在声明后不能被跳转。
fn foo() -> i32
{
var x = 0;
goto end;
x = 10; // This line is not executed.
end:
x = x + 1;
return: x
}
作用域循环语句
返回的唯一方式是使用loop语句。
fn foo() -> i32
{
var x = 0;
{
x = x + 1;
loop;
}
// This line is never reached.
return: x
}
视图
函数参数,如数组和结构体,以视图形式传递。对于数组而言,这意味着创建了一个数组视图(或“切片”)并将其传递到函数中。数组视图会记住它们数组的长度,可以使用长度操作来访问,如下所示:|x|
。
fn foo()
{
var data: [4]i32 = [1, 2, 3, 4];
var total = sum(data);
}
fn sum(x: []i32) -> i32
{
var total = 0;
var i = 0;
{
if i == |x|
goto return;
total = total + x[i];
i = i + 1;
loop;
}
return: total
}
引用指针
引用指针允许函数修改其参数,但要求调用者显式传递一个地址。
fn foo()
{
var data: [4]i32 = [1, 2, 3, 4];
set_to_zero(&data);
}
fn set_to_zero(x: &[]i32)
{
var i = 0;
{
if i == |x|
goto end;
x[i] = 0;
i = i + 1;
loop;
}
end:
}
与其他大多数语言中的指针不同,引用指针(包括指向指针的指针)会自动解引用到其基类型,任何不是引用指针的类型。
var x: i32 = 17;
var a: &i32 = &x;
var b: &&i32 = &&a;
var y: i32 = b;
b = 30;
// Now x == 30 and y == 17.
要更改引用指针所指向的值,需要显式修改地址。
var x: i32 = 17;
var y: i32 = 30;
var z: i32 = 88;
var a: &i32 = &x;
&a = &y;
// Now a points to y instead of x.
var b: &i32 = &z;
&a = &b;
// Now a and b both point to z.
结构体和词
与数组类似,使用struct
关键字声明的结构体类型隐式地以视图形式传递,不能用作函数的返回值。使用word8
、word16
、word32
、word64
或word128
声明的固定大小结构体会按值传递。
导入
import
关键字用于将标记为pub
的所有函数签名、结构和常量从源文件导入到目标文件。导入本身不是公开的,因此不会被重新导入。
C语言互操作性
标记为extern
的函数使用C ABI,这意味着可以从由LLVM编译的C代码中调用它们。反之,声明一个如下的函数头
extern fn foo(buffer: []u8, length: usize);
允许您从Penne代码中调用C函数。与其他使用或支持C ABI的编程语言(如C++、Rust、Zig或WebAssembly)进行交互也是可能的。
在extern
函数的签名中,只允许使用数组视图、指针和原始类型i8
、i16
、i32
、i64
、u8
、u16
、u32
、u64
和usize
。在extern
函数中,数组视图对应于C中的(const)指针,没有长度(|x|
),且不能为空。在Penne的未来版本中,指针也将假定不为空,并且必须使用“可选”类型来标记可空指针。
结构和常量也可以声明为extern
,但截至v0.3.0,这没有效果。
非特性
Penne是一种专门的语言,不是通用或系统编程语言。一些我们认为对于2023年的好编程语言来说是必不可少的现代特性被省略了。这要么是因为包括它们会与Penne的前提相矛盾(见上文),要么是为了简化其实现。因此,以下明确不是Penne的特性:
- 类;
- 泛型;
- 迭代器;
- 支持大于64位的指针;
- 保证是UTF-8的字符串类型;
- 任何类型的内存安全。
文档
贡献
笔锋及其编译器仍在开发中,许多语言特性(枚举、模块)尚未实现。然而,我的意图是在功能缺失时引发适当的错误消息,直到它们被实现。如果您遇到编译器段错误或恐慌,或者编译器生成无效的LLVM IR,提供最小可复现示例报告问题将非常感激。
许可证
本库由Sander在't Veld创建。根据LICENSE.txt
中指定的MIT许可证提供给您。
软件按“原样”提供,不提供任何形式的保证,无论是明示的还是隐含的,包括但不限于适销性、特定用途的适用性和非侵权性保证。在任何情况下,作者或版权所有者均不对任何索赔、损害或其他责任负责,无论是基于合同、侵权或其他方式,是否由软件、软件的使用或其他交易引起、源自或与此有关。
依赖关系
~4–14MB
~180K SLoC