{"id":17513458,"url":"https://github.com/zituitui/mua-language-interpreter-based-on-java-","last_synced_at":"2025-03-28T22:23:45.299Z","repository":{"id":131835520,"uuid":"474223025","full_name":"zituitui/MUA-language-Interpreter-based-on-Java-","owner":"zituitui","description":"MakeUp Programming Language  Interpreter. ","archived":false,"fork":false,"pushed_at":"2022-03-28T01:02:43.000Z","size":30,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-03T08:48:35.564Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zituitui.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-03-26T02:42:56.000Z","updated_at":"2022-03-26T02:46:28.000Z","dependencies_parsed_at":"2023-04-04T15:48:57.936Z","dependency_job_id":null,"html_url":"https://github.com/zituitui/MUA-language-Interpreter-based-on-Java-","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zituitui%2FMUA-language-Interpreter-based-on-Java-","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zituitui%2FMUA-language-Interpreter-based-on-Java-/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zituitui%2FMUA-language-Interpreter-based-on-Java-/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zituitui%2FMUA-language-Interpreter-based-on-Java-/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zituitui","download_url":"https://codeload.github.com/zituitui/MUA-language-Interpreter-based-on-Java-/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246107411,"owners_count":20724539,"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":[],"created_at":"2024-10-20T06:26:31.601Z","updated_at":"2025-03-28T22:23:45.256Z","avatar_url":"https://github.com/zituitui.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# MakeUp Programming Language\n\nRevised 2021-11-14\n\n## 基本数据类型value\n\n数字number，字word，表list，布尔bool\n\n* 任何值之间都以空格分隔\n* 数字的字面量以[0~9]或'-'开头，不区分整数，浮点数\n* 字的字面量以双引号`\"`开头，不含空格，采用Unicode编码。在`\"`后的任何内容，直到空格（包括空格、tab和回车）为止的字符（不含空格），都是这个字的一部分，包括其中可能有的\"和[]等符号\n* 表的字面量以方括号`[]`包含，其中的元素以空格分隔；元素可是任意类型；元素类型可不一致\n  * 表的第一个元素和`[`之间，以及最后一个元素和`]`之间不需要有空格分隔\n  * 表中的字不需要`\"`引导\n  * 这是一个有三层表的字面量的例子：`[a [b [c d] e]]`\n* 布尔量只有两个值：`true`和`false`\n* 数字和布尔量在计算时可以被看作是字的特殊形式，即在字面量和变量中的字，当其中的内容是数字或布尔量时，总是可以根据需要自动被转换成数字或布尔量\n\n## 名字name\n\n一个只含有字母和数字及下划线的字，可以用做名字，名字区分大小写。\n\n## 基本操作operation\n\n基本形式：操作名 参数\n\n操作名是一个名字，与参数间以空格分隔。参数可以有多个，多个参数间以空格分隔。每个操作所需的参数数量是确定的，所以不需要括号或语句结束符号。所有的操作都有返回值。\n\n一个程序就是操作的序列。\n\n基本操作有：\n\n* `make \u003cname\u003e \u003cvalue\u003e`： 将value绑定到name上，绑定后的名字位于当前命名空间，返回value。此文档中的基本操作的名字不能重新命名\n* `thing \u003cname\u003e`：返回word所绑定的值\n* `:\u003cname\u003e`：与thing相同\n* `print \u003cvalue\u003e`：输出value，返回这个value\n* `read`：返回一个从标准输入读取的数字或字\n* 运算符operator\n  * `add`, `sub`, `mul`, `div`, `mod`：`\u003coperator\u003e \u003cnumber\u003e \u003cnumber\u003e`\n\n*⬆️ 第一次提交做到这里 ⬆️*\n\n测试共 10 分。\n\n---\n\n* `erase \u003cname\u003e`：清除word所绑定的值，返回原绑定的值\n* `isname \u003cword\u003e`：返回word是否是一个名字，true/false\n* `run \u003clist\u003e`：运行list中的代码，返回list中执行的最后一个op的返回值\n* `eq`, `gt`, `lt`：`\u003coperator\u003e \u003cnumber|word\u003e \u003cnumber|word\u003e`\n* `and`, `or`：`\u003coperator\u003e \u003cbool\u003e \u003cbool\u003e`\n* `not`：`not \u003cbool\u003e`\n\n### 判断\n\n* `if \u003cbool\u003e \u003clist1\u003e \u003clist2\u003e`：如果bool为真，则执行list1，否则执行list2。list均可以为空表，返回list1或list2执行后的结果。如果被执行的是空表，返回空表。如果被执行的表只有一项，且非OP，返回该项。\n* `isnumber \u003cvalue\u003e`：返回value是否是数字 \n* `isword \u003cvalue\u003e`：返回value是否是字\n* `islist \u003cvalue\u003e`：返回value是否是表 \n* `isbool \u003cvalue\u003e`：返回value是否是布尔量 \n* `isempty \u003cword|list\u003e`: 返回word/list是否是空字/空列表\n\n## 函数定义和调用\n\n### 定义\n\n`make \u003cname\u003e [\u003clist1\u003e \u003clist2\u003e]`，其中：\n\t\n\n* name为函数名\n* list1为参数表\n* list2为操作表\n\n以下为函数定义的例子：\n\t\n\n```\nmake \"prt [\n  [a]\n  [print :a]\n]\n```\n\n### 调用\n\n`\u003cfunctionName\u003e \u003carglist\u003e`，其中：\n\n* \u003cfunctionName\u003e为make中定义的函数名，不需要双引号\"\n* \u003carglist\u003e是参数表，\u003carglist\u003e中的值和函数定义时的\u003clist1\u003e中名字进行一一对应绑定\n\n以下为函数调用的例子：`prt \"hello`\n\n### 本地变量（第二阶段）\n\n以下规则仅适用于第二阶段评测。本地变量的规则在第三阶段将会调整。\n\n* 在函数中访问（读取）变量的值的时候，首先访问本地，如果本地不存在，则访问全局\n* 在函数中做`make`时，永远只写本地：\n      1. 检查本函数内是否存在这个名字，如果存在，则对已有的变量赋值；\n      2. 否，则在本地定义一个新的变量\n* 在函数内`make`出来的函数只在该函数内有效，但是这样的函数并不会访问定义它的函数的本地变量，它的外部仍然直接就是全局变量区\n\n### 函数相关的操作\n\n* `return \u003cvalue\u003e`：停止执行函数，设定value为返回给调用者的值\n* `export \u003cname\u003e`：将本地`make`的变量`\u003cname\u003e`输出到全局，返回它的值：\n  * 如果全局没有这个变量，则增加一个全局变量\n  * 如果全局已经有了同名的变量，则替换全局变量的值\n  * 在函数内`make`出来的函数一样可以被`export`到全部\n\n*⬆️ 第二次提交做到这里 ⬆️*\n\n自测数据共 50 分；\n线上 CI 测试共 60 分。\n\n---\n\n## 简单函数式编程\n\n首先先介绍两个重要概念。\n\n### 闭包\n\n闭包的定义：如果函数 `f` 内定义了函数 `g`，那么如果 `g` 存在自由变量（即 `g` 中未定义的变量），那么将产生闭包。根据以上定义，实现闭包需要支持两项功能：\n\n1. 函数内定义函数；\n\n   这很简单。因为 MUA 函数与表没有区别，所以实际上函数内定义函数就是函数内定义表。\n\n2. 函数可以**对上文进行值捕获**。\n\n   我们通过一个简单的例子来了解捕获的概念。\n\n   ```\n   make \"f [[x] [\n     make \"g [[y] [return add :x :y]]\n     return g 42\n   ]]\n   print f 233\n   ```\n   \n   上面的函数 `f` 中嵌套定义了函数 `g`。函数 `g` 中存在自由变量 `x`，函数 `g` 成为闭包，捕获上文中的变量 `x`，即在闭包定义时，变量 `x` 被添加到闭包的作用域中。注意，我们捕获的是值，不是引用，闭包不会对被捕获变量本身产生副作用。那么如果运行以下代码：\n   \n   ```\n   print f 233\n   ```\n   \n   结果应输出 `275`。一言以蔽之，闭包就是“代码 + 环境”。\n\n### 高阶函数\n\n高阶函数是至少满足下列一个条件的函数：\n\n* 接受一个或多个函数作为输入\n* 输出一个函数\n\n根据以上定义，实现高阶函数需要支持两项功能：\n\n* 函数可以接受一个或多个函数作为输入\n\n  因为 MUA 函数与表没有区别，所以接受函数作为输入就是接受列表作为输入，但我们还需要 track 输入的函数的环境。\n\n* 函数可以输出一个函数\n\n  因为 MUA 函数与表没有区别，所以**简单来说**输出一个函数就是输出一个表，但我们还需要 track 输出的函数的环境。\n\n### 简单函数式编程\n\n有了以上两大特性，MUA 真正意义上支持了函数式编程，即函数为“一等公民”，和变量地位等同。接下来介绍一个函数式编程综合应用。\n\n```\nmake \"f1 [[x] [\n    make \"g1 [[y] [return add :x :y]]\n    return :g1\n  ]\n]\nmake \"c1 f1 42\nmake \"c2 f1 24\nprint c1 1\nprint c2 2\n```\n\n`f1` 接受一个 `x` 参数，返回一个闭包 `g1`，闭包环境为 `x` 与 `y`。调用 `f1` 即返回闭包 `g1`。那么对于 `c1` 闭包来说，其环境是 `x = 42`；对于 `c2` 闭包来说，其环境是 `x = 24`。随后我们输出调用 `c1` 与 `c2` 的结果，输出是：\n\n```\n43\n26\n```\n\n补充一个柯里化例子。柯里化是把接受多个参数的函数变换成接受一个单一参数（最初函数的第一个参数）的函数，并且返回接受余下的参数而且返回结果的新函数的技术。\n\n```\nmake \"curry_two [[f x] [\n  return [[y] [return f :x :y]]\n]]\nmake \"f2 [[x y] [\n  return add :x :y\n]]\nmake \"f2p curry_two :f2 42\n```\n上面的函数 `curry_two` 接受函数 `f` 及其需要的第一个参数，返回一个接受剩下一个参数的函数闭包。闭包捕获了环境中的 `f` 与 `x`。`f2` 是需要两个参数的函数，将 `f2` 及其第一个参数传入 `curry_two`，得到一个新函数，其接受一个参数（即原 `f2` 的第二个参数），返回该参数与 42 的和。因此有下面程序\n\n```\nprint f2p 233\n```\n\n输出结果为 275。\n\n### 任务与一些说明\n\n综合以上背景知识，你需要实现以下特性：\n\n* 闭包。嵌套可能有多层。\n* 高阶函数。\n\n总的来说，本阶段的实现重点在于你需要跟踪每个函数的**环境**。处理多层嵌套时可以考虑维护一个环境的栈。\n\n我们在测试时依然会公布测试数据供你检验程序的正确性。总体来说，大部分分数的测试数据不会太复杂。\n\n同时在原规则中，对于本地变量的要求是\n\n\u003e 访问变量值时首先访问本地，如果本地不存在则访问全局。在函数内 make 出来的函数只在该函数内有效，但是这样的函数并不能访问定义它的函数的本地变量，它的外部仍然直接就是全局变量区。\n\n支持闭包和高阶函数的 MUA 则不适用以上要求，应为：嵌套定义的函数访问变量时先访问本地，本地不存在则访问定义它函数的本地变量，然后再访问全局变量区。\n\n*⬆️ 第三次提交做到这里 ⬆️*\n\n---\n\n\n## 字表处理\n\n* `readlist`：返回一个从标准输入读取的一行，构成一个表，行中每个以空格分隔的部分是list的一个元素，元素的类型为字\n  * 用`readlist`读入的只可能是单层的表\n* `word \u003cword\u003e \u003cword|number|bool\u003e`：将两个word合并为一个word，第二个值可以是word、number或bool\n* `sentence \u003cvalue1\u003e \u003cvalue2\u003e`：将value1和value2合并成一个表，两个值的元素并列，value1的在value2的前面\n* `list \u003cvalue1\u003e \u003cvalue2\u003e`：将两个值合并为一个表，如果值为表，则不打开这个表\n* `join \u003clist\u003e \u003cvalue\u003e`：将value作为list的最后一个元素加入到list中（如果value是表，则整个value成为表的最后一个元素）\n* `first \u003cword|list\u003e`：返回word的第一个字符，或list的第一个元素\n* `last \u003cword|list\u003e`：返回word的最后一个字符，list的最后一个元素\n* `butfirst \u003cword|list\u003e`：返回除第一个元素外剩下的表，或除第一个字符外剩下的字\n* `butlast \u003cword|list\u003e`：返回除最后一个元素外剩下的表，或除最后一个字符外剩下的字\n\n## 数值计算\n\n* `random \u003cnumber\u003e`：返回[0,number)的一个随机数\n* `int \u003cnumber\u003e`: floor the int\n* `sqrt \u003cnumber\u003e`：返回number的平方根\n\n## 其他操作\n\n* `save \u003cword\u003e`：以源码形式保存当前命名空间在word文件中，返回文件名\n* `load \u003cword\u003e`：从word文件中装载内容，加入当前命名空间，返回true\n* `erall`：清除当前命名空间的全部内容，返回true\n* `poall`：返回当前命名空间的全部名字的list\n\n## 既有名字\n\n系统提供了一些常用的量，或可以由其他操作实现但是常用的操作，作为固有的名字。这些名字是可以被删除（erase）的。\n\n* `pi`：3.14159\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzituitui%2Fmua-language-interpreter-based-on-java-","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzituitui%2Fmua-language-interpreter-based-on-java-","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzituitui%2Fmua-language-interpreter-based-on-java-/lists"}