{"id":13782949,"url":"https://github.com/AloneCafe/l2","last_synced_at":"2025-05-11T16:33:35.623Z","repository":{"id":154136171,"uuid":"165468647","full_name":"AloneCafe/l2","owner":"AloneCafe","description":"一种简单的、动态弱类型的、解释型的脚本编程语言，及其脚本解释器的设计与实现","archived":false,"fork":false,"pushed_at":"2021-04-20T17:34:41.000Z","size":136,"stargazers_count":4,"open_issues_count":0,"forks_count":1,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-04-25T05:03:34.128Z","etag":null,"topics":["hard-coded","interpreter","lambda","programming-language","pure-c","weak-typed"],"latest_commit_sha":null,"homepage":"https://github.com/AloneCafe/l2","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/AloneCafe.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2019-01-13T05:15:46.000Z","updated_at":"2022-08-30T09:32:11.000Z","dependencies_parsed_at":"2024-01-07T23:08:47.441Z","dependency_job_id":"32c1e2cf-539f-46aa-9ee8-e7fd999c240b","html_url":"https://github.com/AloneCafe/l2","commit_stats":null,"previous_names":["yenyuloong/l2"],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AloneCafe%2Fl2","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AloneCafe%2Fl2/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AloneCafe%2Fl2/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AloneCafe%2Fl2/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/AloneCafe","download_url":"https://codeload.github.com/AloneCafe/l2/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252961820,"owners_count":21832194,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["hard-coded","interpreter","lambda","programming-language","pure-c","weak-typed"],"created_at":"2024-08-03T18:01:48.898Z","updated_at":"2025-05-11T16:33:35.336Z","avatar_url":"https://github.com/AloneCafe.png","language":"C","funding_links":[],"categories":["C"],"sub_categories":[],"readme":"### 一种简单的、弱类型的、解释型的脚本编程语言，及其脚本解释器的设计与实现\n#### 暂且叫 L2 编程语言吧 (恕本人水平有限，纯 C 的代码过于冗杂，PS: 目前本人已弃坑)\n---\n\n### 解释器用途\n* 可作为课题设计或课程设计\n* 开发者可自行扩展解释器功能，比如作为嵌入式编程语言使用\n* 同样可以作为玩具把玩（逃\n\n### 从源代码开始构建\n  可使用 CMake 和 MinGW/GCC 按照 ```CMakeList.txt``` 中所述构建可执行文件，代码模块结构简单，本人不再赘述\n\n---\n\n### L2 编程语言\n- [L2 编程语言简要说明](#l2-编程语言简要说明)\n  - [类 C 的语法](#类-c-的语法)\n  - [语法关键字（14 个）](#语法关键字14-个)\n  - [仅支持单行的注释](#仅支持单行的注释)\n  - [基本类型](#基本类型)\n  - [var 关键字](#变量定义和赋值var-关键字)\n  - [proc 关键字](#函数过程的定义和使用proc-关键字)\n  - [运算符与优先级](#运算符与优先级)\n  - [作用域](#作用域)\n  - [eval 关键字](#任意复杂的表达式的评估eval-关键字)\n  - [程序分支](#程序分支if-elif-else)\n  - [循环和迭代](#循环和迭代forwhile-和-do-while)\n\n- [L2 编程语言的一些技巧](#l2-编程语言的一些技巧)\n  - [过程 lambda 化](#过程-lambda-化)\n  - [高阶过程（回调过程）](#高阶过程回调过程)\n  \n  \n---\n\n### 未完成的 features\n* 尚未实现**字符串**（string）支持\n* 尚未实现**原生数组**（native array）支持\n* 尚未实现基本的**对象系统**（objective system）\n* 尚未实现对程序中对**标准输入**（standard input）的支持\n\n---\n\n## L2 编程语言简要说明\n\n### 类 C 的语法\nL2 编程语言与 C、C++、Java、JS 等编程语言的语法类似\n\n### 语法关键字（14 个）\ntrue, false, var, if, else, elif, while, do, for, break, continue, return, proc, eval\n\n### 仅支持单行的注释\n* 由 ``` // ``` 开始到行尾结束的一段内容将自动被解释器忽略\n\n### 基本类型\n* 实数型（64 位有符号浮点数）\n* 整数型（64 位有符号整数）\n* 布尔型\n* 过程型（或者叫函数型、lambda 型）\n\u003e lambda 型之上可进行的操作有可实现性，但是本人已弃坑，只保留了极为有限的 lambda 语法\n（其实也算不上，目前变量无法直接赋值为过程，但是可以通过参数传递过程型变量）\n\n### 变量定义和赋值（var 关键字）\n* 示例 L2 代码\n```JavaScript\nvar a = 0;        // 定义变量 a 并且初始化为整数 0\nvar b;            // 定义变量 b, 但是暂不初始化\nb = 4;            // 将变量 b 赋值为整数 4\nvar pi = 3.14;    // 定义变量 pi，并且初始化为实数 3.14 \nvar b = true;     // 定义变量 b，并且初始化为布尔值 true\n```\n\u003e 若不定义变量或者不初始化变量，该变量均无法在表达式中正常使用；若试图使用，解释器将会报告错误\n\n\u003e 变量赋值时，变量的类型可能会发生变化，这与赋给它的新值的类型相关（变量类型的可变性）\n\n### 函数（过程）的定义和使用（proc 关键字）\n* 定义不带参的过程\n```JavaScript\nproc pi() {\n  return 3.14159;\n}\n```\n* 定义带参的过程\n```JavaScript\nproc area(r) {\n  return r * r * pi();\n}\n```\n* 嵌套定义的过程（综合前两个过程）\n```JavaScript\nproc area(r) {\n  proc pi() {\n    return 3.14159;\n  }\n  return r * r * pi();\n}\n```\n* 调用过程\n```JavaScript\nvar d = 10;             // 直径\nvar s = area(d / 2);    // 变量 s 将得到 5 * 5 * 3.14159 的初始值（这个我就不算了）\n```\n\u003e 过程调用时，形参和实参名字可以不同，但是参数数量必须保持一致\n\n\u003e 函数可以嵌套定义\n\n\u003e 与一些类 C 的编程语言类似，``` return ```关键字用于结束过程调用，\n并返回一个有效的值（如果调用者需要这个值进行运算的话，返回值是必须的，否则可以不返回值）\n\n### 运算符与优先级\n| 优先级 | 运算作用 | 顺序 \u0026 结合性 | 运算符 |\n|:---:|:---|:---|:---:|\n| 1 | 逻辑非 | 从左到右，右结合 | ! |\n| 1 | 按位取反 | 从左到右，右结合 | ~ |\n| 1 | 负号 | 从左到右，左结合 | - |\n| 2 | 乘 | 从左到右，左结合 | * |\n| 2 | 除 | 从左到右，左结合 | / |\n| 2 | 取余 | 从左到右，左结合 | % |\n| 3 | 加 | 从左到右，左结合 | + |\n| 3 | 减 | 从左到右，左结合 | - |\n| 4 | 左移 | 从左到右，左结合 | \u003c\u003c |\n| 4 | 右移 | 从左到右，左结合 | \u003e\u003e |\n| 4 | 无符号右移 | 从左到右，左结合 | \u003e\u003e\u003e |\n| 5 | 大于等于 | 从左到右，左结合 | \u003e= |\n| 5 | 大于 | 从左到右，左结合 | \u003e |\n| 5 | 小于等于 | 从左到右，左结合 | \u003c= |\n| 5 | 小于 | 从左到右，左结合 | \u003c |\n| 6 | 不等于 | 从左到右，左结合 | != |\n| 6 | 等于 | 从左到右，左结合 | == |\n| 7 | 按位与 | 从左到右，左结合 | \u0026 |\n| 8 | 按位异或 | 从左到右，左结合 | ^ |\n| 9 | 按位或 | 从左到右，左结合 | \\| |\n| 10 | 逻辑与 | 从左到右，左结合 | \u0026\u0026 |\n| 11 | 逻辑或 | 从左到右，左结合 | \\|\\| |\n| 12 | 条件 | 特殊 | ? : |\n| 13 | 赋值 | 从左到右，右结合 | = |\n| 13 | 除赋值 | 从左到右，右结合 | /= |\n| 13 | 乘赋值 | 从左到右，右结合 | \\*= |\n| 13 | 取余赋值 | 从左到右，右结合 | %= |\n| 13 | 加赋值 | 从左到右，右结合 | += |\n| 13 | 减赋值 | 从左到右，右结合 | -= |\n| 13 | 左移赋值 | 从左到右，右结合 | \u003c\u003c= |\n| 13 | 右移赋值 | 从左到右，右结合 | \u003e\u003e= |\n| 13 | 无符号右移赋值 | 从左到右，右结合 | \u003e\u003e\u003e= |\n| 13 | 按位与赋值 | 从左到右，右结合 | \u0026= |\n| 13 | 按位异或赋值 | 从左到右，右结合 | ^= |\n| 13 | 按位或赋值 | 从左到右，右结合 | \\|= |\n| 14 | 逗号 | 从左到右，左结合 | , |\n\n\u003e 不支持 ++、-- 这种在类 C 编程语言中常见的单目运算符\n\n### 作用域\n无论是过程的定义还是变量的定义，它们在以下两个位置都可以正常使用\n* 定义的下文\n* 定义的下文的所有的子作用域（包含嵌套）\n\n### 任意复杂的表达式的评估（eval 关键字）\n* 示例 L2 代码\n```JavaScript\neval 5 + 3;       // 将输出 8\nvar pi = 3.14;\nvar r = 2;\neval r * r * pi;  // 将输出 12.56\neval pi();        // 当然，评估某个已定义的函数的返回值也是可行的\n```\n\u003e eval 关键字的右侧可以是任意复杂的表达式\n\n### 程序分支（if-elif-else）\n* 示例 L2 代码\n```JavaScript\nvar a = 3;\nvar b = 3;\nif (a == b) {\n  // 处理等于的情形 ...\n} elif ( a \u003c b ) {\n  // 处理小于的情形 ...\n} else {\n  // 处理大于的情形 ...\n}\n```\n\u003e if 和 elif 的表达式的计算结果必须是布尔型的，最终的表达式结果\n必须由 ``` == \u003c= \u003e= != ! \u0026\u0026 || ``` 等这些运算符或者布尔型变量复合作用而成\n\n\u003e if...elif...else 结构的每一个子块都必须使用花括号括起，L2 中不允许出现单条语句或者空语句，子块必须以语句块的形式出现\n\n### 循环和迭代（for、while 和 do-while）\n* for 循环示例\n```JavaScript\nfor (var i = 0; i \u003c 10; i += 1) {   // 该循环体将被执行 10 次\n  // 这里做一些操作\n}\n```\n* while 循环示例\n```JavaScript\nvar i = 0;\nwhile (i \u003c 5) {\n  // 这里做一些操作\n  i += 1;   // 递增循环变量，该循环体将被执行 5 次\n}\n```\n* do...while 循环示例\n```JavaScript\nvar i = 0;\ndo {\n  // 这里做一些操作\n  i += 1;   // 递增循环变量，该循环体将被执行 5 次\n} while (i \u003c 5);\n```\n\n\u003e 这里 ```break``` 、 ```continue``` 这些循环体独有的语句与类 C 编程语言类似，不再多说\n\n\u003e if...elif...else 结构的每一个子块都必须使用花括号括起，L2 中不允许出现单条语句或者空语句，子块必须以语句块的形式出现\n---\n\n## L2 编程语言的一些技巧\n\n### 过程 lambda 化\n在 L2 编程语言中，可以将一个过程赋值给一个变量，或用于初始化某个变量\n* L2 代码示例\n```JavaScript\n// 定义过程 pi\nproc pi() {\n  return 3.14159;\n}\n\n// 过程 lambda 化，p 被初始化成过程\nvar p = pi;\n// 调用过程\np();\n```\n\n### 高阶过程（回调过程）\n在 L2 编程语言中，可以将一个过程作为另一个过程的参数（当然也可以是自身）\n* L2 代码示例\n```JavaScript\n// 定义过程 area\nproc area(r, callproc) {\n  return r * r * callproc();  // 调用者必须提供一个过程，用于产生某个精度的 pi 值\n}\n\n// 定义一个生成保留 2 位小数的 pi2 过程\nproc pi2() { return 3.14; }\n\n// 定义一个生成保留 5 位小数的 pi5 过程\nproc pi5() { return 3.14159; }\n\n// 使用保留了 2 位小数的 pi 值来计算半径为 2 的圆面积，并输出\neval area(2, pi2);\n\n// 使用保留了 5 位小数的 pi 值来计算半径为 2 的圆面积，并输出\neval area(2, pi5);\n\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FAloneCafe%2Fl2","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FAloneCafe%2Fl2","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FAloneCafe%2Fl2/lists"}