GraceLanguage

GraceLanguage 提供了一种图灵完备的脚本语言,可用于电子表格计算、数据库操作或游戏引擎等应用程序。

概述

Grace 是一种完全用纯 Swift 编写的 图灵完备 脚本语言,可用于电子表格计算、数据库操作或游戏引擎等应用程序。

Grace 支持全局和局部变量、枚举、库、函数以及有限的结构支持(参见Grace 变量 > 使用结构文档)等特性。此外,Grace 的设计使其可以很容易地通过注册外部函数来扩展。这使得 Grace 可以与其宿主语言和程序完全互操作。

Grace 的命名是为了纪念 格蕾丝·穆雷·霍珀海军上将。她不仅提出了高级计算机编程语言的想法,而且我们还要感谢她创造了“调试”这个术语。

来自维基百科

她是哈佛 Mark I 计算机的首批程序员之一,也是计算机编程的先驱。霍珀是第一个提出机器无关编程语言理论的人,她使用该理论创建的 FLOW-MATIC 编程语言后来被扩展为 COBOL,这是一种至今仍在使用的早期高级编程语言。

支持

如果您发现 GraceLanguage 有用,并希望帮助支持其持续开发和维护,请考虑进行小额捐赠,尤其是在您将其用于商业产品时

Buy Me A Coffee

正是通过像您这样的贡献者的支持,我才能继续免费构建、发布和维护高质量、文档完善的 Swift 包,如 GraceLanguage

安装

Swift Package Manager (Xcode 11 及以上)

  1. 在 Xcode 中,选择 File > Add Package Dependency… 菜单项。
  2. 在对话框中粘贴 https://github.com/Appracatappra/GraceLanguage.git
  3. 按照 Xcode 的指示完成安装。

为什么不用 CocoaPods 或 Carthage 等?

支持多个依赖管理器会使维护一个库的复杂性和所需时间呈指数级增长。

由于 Swift Package Manager 与 Xcode 11(及更高版本)集成,因此它是未来支持的最简单选择。

基本语法和结构

在 Grace 中,枚举结构函数全局空间中定义,以及一个特殊的函数 main,它充当程序的主要入口点。

此外,库的 导入变量 可以在全局空间中定义,它们将在整个 Grace 程序中可用。 StandardLib 包含诸如 printprintf 之类的内置函数。 StringLib 包含诸如 leftStringmidString 之类的字符串操作函数。

让我们看一个简单的 Grace 程序,看看它是如何工作的

import StandardLib;

enumeration Colors {
    red,
    orange,
    yellow,
    green,
    blue,
    indigo,
    violet
}

structure FullName {
    first:string,
    last:string
}

main {
    var n:int;
    var words:string array = ["One", "Two", "Three", "Four"];
    var color:enumeration Colors = #Color~green;
    var person:structure FullName = new FullName(first:"Jane", last:"Doe");
    var name:string = @join($person~first, "!");
    
    let $n = (@count($words) - 1);
    
    if ($words[$n] = "Four") {
        call @print("It is four.");
    } else {
        call @print("It is not four.");
    }
    
    iterate word in $words {
        call @print($word);
    }
    
    call @sayHello($name);
}

function join(a:string, b:string) returns string {
    return ($a + $b);
}

function sayHello($name:string) {
    call @printf("Hello {0}", [$name]);
}

这里有几点需要指出

为什么要使用特殊的解引用字符?

在设计 Grace Language 时,我的主要驱动因素之一是保持语言的小巧、轻便和快速。 为了实现这个目标,我选择在使用 decorators (装饰器) 解引用 函数变量枚举 时。

这使我可以保持 GraceCompiler 快速和小巧,因为 decorator (装饰器) 会告诉编译器它正在处理的内容,而不会给开发人员带来太大的负担,也不会使语言过于混乱。

这也是为什么您使用 letcall 关键字来修改变量和调用函数,以及为什么表达式总是遵循 (value operator value) 形式的原因。

这些让步避免了 GraceCompiler 必须确定开发人员的意图,从而加快了编译过程。

编译和执行 Grace

GraceLanguage Package 具有编译和运行用 Grace 编写的程序的工具。

GraceCompiler

GraceCompiler 将包含 Grace 程序的 string (字符串) 或文本文件转换为字节码,以便更快地执行。

您可以使用 GraceCompiler 预编译您的 Grace 程序,也可以调用 GraceRuntime 的方法来一步编译和执行 Grace 程序。

此外,您可以创建自己的 GraceCompiler 实例,也可以使用通用的共享实例 GraceCompiler.shared

以下是预编译 Grace 程序的示例

import GraceLanguage;

var program:String {
    return """
    main {
    	call @print("Hello World!");
    }
    """
}

do {
	let executable = try GraceCompiler.shared.compile(program: program)
} catch {
	print("Error: \(error)")
}

有关更多信息,请参阅随附的文档。

GraceRuntime

GraceRuntime 可以执行预编译的 Grace 程序,也可以一步编译和执行程序。

以下是一步编译和执行程序的示例

import GraceLanguage;

var program:String {
    return """
    main {
    	call @print("Hello World!");
    }
    """
}

do {
	try GraceRuntime.shared.run(program: program)
} catch {
	print("Error: \(error)")
}

此外,您可以使用以下命令运行一段 Grace 代码,而无需必需的 main function (主函数)

do {
	try GraceRuntime.shared.run(script: "call @print('Hello World!');")
} catch {
	print("Error: \(error)")
}

使用此函数,代码段将在编译和执行之前包装在以下 Grace 代码中

import StandardLib;
import StringLib;
import MacroLib;

main{
	// Your code goes here...
}

返回执行结果

内置于 GraceCompiler 中的所有执行方法都可以将结果返回给调用程序。 例如

let code = """
import StandardLib;
    
main {
    var n:int = 5;
    var x:int = 5;
    
    return ($n + $x);
}
"""
    
let result = try GraceRuntime.shared.run(program: code)
print("The result is: \(result?.int)")

执行上述代码后,result 将是一个包含 10GraceVariable

扩展字符串宏

GraceRuntime.expandMacros 函数可以通过执行指定的函数并将结果插入字符串中来扩展给定字符串内的 Grace 函数宏。 例如

let text = GraceRuntime.shared.expandMacros(in: "The answer is: @intMath(40,'+',2)")

运行上述代码后,text 的值将为 The answer is: 42

有关更多信息,请参阅随附的文档。

文档

Package 包含了所有功能的完整 DocC Documentation (DocC 文档)。